package com.eactive.eai.transformer.engine;

import org.springframework.stereotype.Component;

import com.eactive.eai.common.lifecycle.Lifecycle;
import com.eactive.eai.common.lifecycle.LifecycleException;
import com.eactive.eai.common.lifecycle.LifecycleListener;
import com.eactive.eai.common.lifecycle.LifecycleSupport;
import com.eactive.eai.common.util.ApplicationContextProvider;
import com.eactive.eai.transformer.function.FunctionManager;
import com.eactive.eai.transformer.layout.LayoutManager;
import com.eactive.eai.transformer.layout.LayoutTypeManager;
import com.eactive.eai.transformer.transform.TransformManager;
import com.eactive.eai.transformer.util.Logger;

@Component
public class TransformEngine implements Lifecycle {

    private static Logger logger = Logger.getLogger("transformer");
    private Transformer transformer;
    private LifecycleSupport lifecycleSupport = null;
    private boolean started;

    
    private TransformEngine() {
        lifecycleSupport = new LifecycleSupport(this);
        transformer = new Transformer();
    }

    private void initEngine() throws LifecycleException {
    	Runtime runtime = Runtime.getRuntime();
    	long memUnit = 1024;
    	logger.info("INIT Usage("+memUnit+") : "+ (runtime.totalMemory() - runtime.freeMemory())/memUnit + " / " +runtime.totalMemory()/memUnit);
    	FunctionManager.getInstance().start();
    	logger.info("FUNC Usage("+memUnit+") : "+ (runtime.totalMemory() - runtime.freeMemory())/memUnit + " / " +runtime.totalMemory()/memUnit);
    	LayoutTypeManager.getInstance().start();
    	logger.info("LTYP Usage("+memUnit+") : "+ (runtime.totalMemory() - runtime.freeMemory())/memUnit + " / " +runtime.totalMemory()/memUnit);
    	LayoutManager.getManager().start();
    	logger.info("LOUT Usage("+memUnit+") : "+ (runtime.totalMemory() - runtime.freeMemory())/memUnit + " / " +runtime.totalMemory()/memUnit);
    	TransformManager.getManager().start();
    	logger.info("TRAN Usage("+memUnit+") : "+ (runtime.totalMemory() - runtime.freeMemory())/memUnit + " / " +runtime.totalMemory()/memUnit);
    	
        ParserFactory.activeCount();
    }

    private void clearEngine() throws LifecycleException {
        LayoutTypeManager.getInstance().stop();
        FunctionManager.getInstance().stop();
        LayoutManager.getManager().stop();
        TransformManager.getManager().stop();
    }

    public static TransformEngine getInstance() {
        return ApplicationContextProvider.getContext().getBean(TransformEngine.class);
    }

    /**
     * 변환 처리용 인스턴스를 가져옴.
     */
    public Transformer getTransformer() {
        return transformer;
    }

    public void addLifecycleListener(LifecycleListener listener) {
        lifecycleSupport.addLifecycleListener(listener);
    }

    public LifecycleListener[] findLifecycleListeners() {
        return lifecycleSupport.findLifecycleListeners();
    }

    public void removeLifecycleListener(LifecycleListener listener) {
        lifecycleSupport.removeLifecycleListener(listener);
    }

    public void start() throws LifecycleException {
        if (isStarted())
            return;
            
        try {
            initEngine();
            this.started = true;
        } catch (LifecycleException e) {
            throw e;
        } catch (Exception e) {
            throw new LifecycleException(e);
        }
    }

    public boolean isStarted() {
        return this.started;
    }

    public void stop() throws LifecycleException {
        try {
            clearEngine();
            this.started = false;
        } catch (LifecycleException e) {
            throw e;
        } catch (Exception e) {
            throw new LifecycleException(e);
        }
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(FunctionManager.getInstance().toString() + "\n");
        sb.append(LayoutTypeManager.getInstance().toString() + "\n");
        sb.append(LayoutManager.getManager().toString() + "\n");
        sb.append(TransformManager.getManager().toString());

        return sb.toString();
    }
}
