package com.eactive.eai.common.web;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import javax.sql.DataSource;
import com.eactive.eai.adapter.socket.config.SocketAdapterManager;
import com.eactive.eai.batch.scheduler.SchedulerMessageManager;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.lifecycle.Lifecycle;
import com.eactive.eai.common.lifecycle.LifecycleException;
import com.eactive.eai.common.lifecycle.LifecycleManager;
import com.eactive.eai.common.property.PropManager;
import com.eactive.eai.common.dao.Keys;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.common.util.ServiceLocator;
import com.eactive.eai.common.util.ServiceLocatorException;

/**
 * 1. 기능 : EAI FrameWork이 초기화(Deploy)될 때 실행되어야 할 작업을 정의
 * 2. 처리 개요 : Logger초기화, LifecycleManager를 통한 Manager 초기화
 * *     -
 * 3. 주의사항
 *
 * @author  :
 * @version : v 1.0.0
 * @see : Logger.java, LifecycleManager.java
 * @since   :
 */
public class AppInitializer implements InitializingBean, DisposableBean { 

	private DataSource dataSource;
	
	private String instName;
	
	private String tableOwner;

	private String systemMode = "D"; //EAI System Mode : [P/T/D/S]
	
	public void setDataSource(DataSource dataSource) {
    	this.dataSource = dataSource;
    }
    
    public void setInstName(String instName) {
    	this.instName = instName;
    }
    
    public void setTableOwner(String tableOwner) {
    	this.tableOwner = tableOwner;
    }
    
    public void setSystemMode(String systemMode) {
    	this.systemMode = systemMode;
    }
    /** 
     * 1. 기능 : EAI FrameWork의 웹어플리케이션이 될 때 초기화 작업을 수행 
     * 2. 처리 개요 : EAI FrameWork의 웹어플리케이션이 디플로이될 때 PropManager, Logger, LifecycleManager를 기동하여
     *     초기화작업을 수행한다. 
     * 3. 주의사항 
     * - appicationContext에 정의된 DataSource를 사용하도록 처리 됨
     * @return void
     * @exception 
     **/

    private void init() 
    {
    	Logger logger = Logger.getLogger("root");
    	String serverName = System.getProperty("inst.Name");
    	if(serverName == null) {
    		System.setProperty("inst.Name", instName);
//    		System.setProperty("weblogic.Name", instName);
    	}
    	
    	String tOwner = System.getProperty(Keys.TABLE_OWNER_KEY);
    	if(tOwner == null) {
    		System.setProperty(Keys.TABLE_OWNER_KEY, tableOwner);
    	}
    	
    	String sMode = System.getProperty(com.eactive.eai.common.server.Keys.EAI_SYSTEMMODE);
    	if(sMode == null) {
    		System.setProperty(com.eactive.eai.common.server.Keys.EAI_SYSTEMMODE, systemMode);
    	}
    	
		// set Spring dataSource to ServiceLoactor
		try {
			ServiceLocator sl = ServiceLocator.getInstance();
			sl.putDataSource(Keys.EAI_DATASOURCE, dataSource);
			System.out.println("\n@@ " + Keys.EAI_DATASOURCE + " = " + dataSource);
		} catch (ServiceLocatorException e1) {
			e1.printStackTrace();
		}
		
        System.out.println("\n@@ ElinkBAP Framework =====================================================");
        System.out.println("@ Batch System Config Initializing---------------------------------- ");
        try {
            String tableOwner = System.getProperty(com.eactive.eai.common.dao.Keys.TABLE_OWNER_KEY);
            String systemMode = System.getProperty(com.eactive.eai.common.server.Keys.EAI_SYSTEMMODE);
            
            if(tableOwner == null || tableOwner.trim().length() == 0 ||
               systemMode == null || systemMode.trim().length() == 0 ) {
                System.out.println("==========================================================================");
                System.out.println("# E R R O R : Batch System Configuration");
                System.out.println("#  Check Start Script Rule table Owner : -D"+com.eactive.eai.common.dao.Keys.TABLE_OWNER_KEY+"=");
                System.out.println("#  Check Start Script Batch System Mode  : -D"+com.eactive.eai.common.server.Keys.EAI_SYSTEMMODE+"=");
                System.out.println("#  Batch System Mode : [P/T/D/S]");                
                System.out.println("==========================================================================");
                throw new Exception(" Rule Table Owner Not Configured ");
            }
            
            System.out.println("==========================================================================");
            System.out.println("# S U C C E S S : Batch System Configuration");
            System.out.println("#  Rule table Owner : "+tableOwner);
            System.out.println("#  Batch System Mode  : "+systemMode);
            System.out.println("#  Batch System Mode : [P(Product)/T(Test)/D(Develop)/S(Simulator)]");                
            System.out.println("==========================================================================");
            
        } catch(Exception e) {
            throw new RuntimeException("EAI System Configuration Error - " + e.getMessage());
        }


        logger.debug("Property 메모리 로딩 시작 ------------------------------------------");
        try {
            PropManager.getInstance().start();
        } catch(LifecycleException e) {
        	logger.error( e.getMessage(), e);
            throw new RuntimeException(ExceptionUtil.getErrorCode(e,"BFCEAICWB001"));
        }
        logger.debug("Property 메모리 로딩 종료 ------------------------------------------");

        logger.debug("Logger 메모리 로딩 시작 ------------------------------------------");
        try {
            Logger.doConfigure();
        } catch(Exception e) {
        	logger.error( e.getMessage(), e);
        }
        logger.debug("Logger 메모리 로딩 종료 ------------------------------------------");
        
        try {
            SchedulerMessageManager.getInstance().deleteJobFromProcessing();
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
        
        try {
			Class clazz = Class
					.forName("com.eactive.eai.rms.client.context.MonitoringContextFactory");
			Object factory = clazz.newInstance();
			Method method = clazz.getMethod("create");
			method.invoke(factory);
			System.out.println("RMSCLIENT AGENT STARTED ~~ !!!!");
			logger.warn("EMSCLIENT AGENT STARTED ~~ !!!!");
		} catch (InvocationTargetException e) {
			System.out.println("RMSCLIENT AGENT CANNOT START ~~ !!!! - "+e.getTargetException().toString());			
			logger.error("RMSCLIENT AGENT CANNOT START ~~ !!!! - "+e.getTargetException().toString(),e.getTargetException());
			e.getTargetException().printStackTrace();			
		} catch (Throwable e) {
			System.out.println("RMSCLIENT AGENT CANNOT START ~~ !!!! - "+e.toString());			
			logger.error("RMSCLIENT AGENT CANNOT START ~~ !!!! - "+e.toString(),e);
		}

        logger.debug("LifeCycle 관련 클래스 메모리 로딩 시작 ------------------------------------------");
        LifecycleManager manager = LifecycleManager.getInstance();
        if(manager instanceof Lifecycle) {
            try {
                manager.start();
            } catch(LifecycleException e) {
            	logger.error( e.getMessage(), e);
                throw new RuntimeException(ExceptionUtil.getErrorCode(e,"BECEAICWB002"));
            }
        }       
        
        logger.debug("LifeCycle 관련 클래스 메모리 로딩 종료 ------------------------------------------");
        logger.debug("배치 프레임웍 Application 초기화 종료!");
    }

    /**
     * 1. 기능 : EAI FrameWork의 웹어플리케이션이 Undeploy될 때 초기화된 Manager들을 중지시킴
     * 2. 처리 개요 : EAI FrameWork의 웹어플리케이션이 Undeploy될 때 LifecycleManager를 통해 Manager를 중지시킨다.
     *
     * 3. 주의사항
     *
     * @param ServletContextEvent
     * @return void
     * @exception
     **/
    public void destroy()
    {
    	Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
        logger.debug("@ eLink Batch Application destroying.");


        LifecycleManager manager = LifecycleManager.getInstance();
        if(manager instanceof Lifecycle) {
            try {
                manager.stop();
            } catch(LifecycleException e) {
                throw new RuntimeException(ExceptionUtil.getErrorCode(e,"BECEAICWB003"));
            }
        }

        try {
            PropManager.getInstance().stop();
        } catch(LifecycleException e) {
            throw new RuntimeException(ExceptionUtil.getErrorCode(e,"BECEAICWB004"));
        }

        try {
            SocketAdapterManager.getInstance().stop();
        } catch ( Exception e ) {
            throw new RuntimeException(ExceptionUtil.getErrorCode(e,"BECEAICWB005"));
        }
        logger.debug("\n\n");
    }
	@Override
	public void afterPropertiesSet() throws Exception {
		init();		
	}

}
