package com.eactive.eai.batch.job.jobComm;

import java.net.Socket;
import java.net.UnknownHostException;

import com.eactive.eai.batch.job.jobHandle.FlowController;
import com.eactive.eai.batch.job.jobHandle.JobFinishHandler;

import com.eactive.eai.adapter.socket.outbound.OutboundSocketClient;
import com.eactive.eai.batch.common.CalendarUtil;
import com.eactive.eai.batch.doc.BatchDoc;
import com.eactive.eai.batch.running.BatchRunningJobManager;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.util.Logger;

public class OutboundSocketHandle {

	private BatchDoc batchDoc;
	private String       logHeader;
	private String strUUID;
	private Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
	
    public void proc( BatchDoc recvBatchDoc ){
    	batchDoc = recvBatchDoc;
    	init();
    	try {
			connect();
			FlowController flowController = new FlowController();
			batchDoc = flowController.clientRequestwithReturn(batchDoc);
			closeAndRemove();
		} catch (Exception e) {
			handleException(e);
		}
    	
    }
    private void init()
    {
        batchDoc.getBatchMsg().getBody().setPhaseStartTime(CalendarUtil.getCurrentTimeNoDash());

		logHeader = "["+ batchDoc.getBatchMsg().getHeader().getUUID() +" / "+
		                 batchDoc.getBatchMsg().getHeader().getProcessCode() +" / "+
		                 batchDoc.getBatchMsg().getHeader().getInstitutionName() +" / "+
		                 batchDoc.getBatchMsg().getHeader().getProcessType() +" / "+
		                 batchDoc.getBatchMsg().getHeader().getFileName() +" / "+
		                 batchDoc.getBatchMsg().getHeader().getRuleCode() +"] [OutboundSocketHandle] ";

		strUUID = batchDoc.getBatchMsg().getHeader().getUUID();

    	logger = batchDoc.getLogger();

        logger.info("{"+logHeader+"} start OutboudnSocketHandle ... " );
        logger.info("{"+logHeader+"} [JUNGFOX]################ 요구송신 소켓연결 JPD  시작 BatchMessageDoc: \n"+ batchDoc.toString());
    }

    private void connect() throws Exception{
		// 새로운 connection 만들기
		// *** 소켓연결은 상대방 서버 소켓의 IP+PORT 당 하나의 연결만을 가지는 것을 가정한다.

		// 2. 연결 가능 IP 주소 구하기
		//    조건 : 현재 사용중이 아니고, 장애통보 혹은 장애 상태가 아닌 경우...
		//
		// 사용가능한 소켓 자원이 구해졌으면
		//
		logger.info("{"+logHeader+"} SOCKET TARGET IP = [" + batchDoc.getBatchMsg().getHeader().getRemoteIP()+"]" );
		logger.info("{} SOCKET PORT = [" + batchDoc.getBatchMsg().getHeader().getPort()+"]");
		// 소켓을 만들고
		logger.info("{"+logHeader+"} Socket connection try to the ["+batchDoc.getBatchMsg().getHeader().getRemoteIP()+"] starting");
		int nPortNum = -1;
		try {
			nPortNum = Integer.parseInt(batchDoc.getBatchMsg().getHeader().getPort());

		} catch (Exception ex) {
			String errMsg = ExceptionUtil.getErrorCode(ex, "BECEAIFJC002", new String[] {batchDoc.getBatchMsg().getHeader().getPort()});
			throw new Exception(errMsg);
		}

		Socket socket = socketInit(batchDoc.getBatchMsg().getHeader().getRemoteIP(), nPortNum);
		if (socket == null) {
			// String errMsg = "setSocketConnection : SocketClientControl socketInit return null";
			String errMsg = ExceptionUtil.getErrorCode("BECEAIFJC003");
			throw new Exception(errMsg);
		}

		logger.info("{"+logHeader+"} Socket connection success");


        logger.info("{"+logHeader+"} >> BatchRunningJobManager 등록시작 ");
        OutboundSocketClient socketClient = new OutboundSocketClient(socket);
        BatchRunningJobManager.getInstance().addRunningJobInfo(strUUID, socketClient, batchDoc);
        logger.info("{"+logHeader+"} >> BatchRunningJobManager 등록완료 ");
    }

    private Socket socketInit(String remoteIP, int remotePort) throws Exception
    {
        try {
            return new Socket(remoteIP, remotePort);
        
        } catch (UnknownHostException ex) {
            String errMsg = ExceptionUtil.getErrorCode(ex, "BECEAIASC001", new String[] {remoteIP, Integer.toString(remotePort)});
            throw new Exception(errMsg);	//Socket 연결 에러 (IP: %1, Port: %2), 서버를 찾을 수 없습니다.
        
        } catch (Exception ex) {
            String errMsg = ExceptionUtil.getErrorCode(ex, "BECEAIASC002", new String[] {remoteIP, Integer.toString(remotePort)});
            throw new Exception(errMsg);	//Socket 연결 에러 (IP: %1, Port: %2), I/O Exception이 발생했습니다.
        }
    }
    private void closeAndRemove() throws Exception
    {
        //Outbound Socket Close
        BatchRunningJobManager.getInstance().closeRunningSocket(strUUID);
        
        logger.info("{"+logHeader+"} >> BatchRunningJobManager 에서 Socket 연결정보 제거 시작......" );
        BatchRunningJobManager.getInstance().removeRunningJobInfo(strUUID);
        logger.info("{"+logHeader+"} >> BatchRunningJobManager Socket 연결정보 제거 완료.");
    }

    private void handleException(Exception ex)
    {
        try {
            if (BatchRunningJobManager.getInstance().isSocketClosed(strUUID) == false) BatchRunningJobManager.getInstance().closeRunningSocket(strUUID);

        } catch (Exception e) {
            logger.error("{"+logHeader+"} ★★★★★ OutboundSocketHandle JPD 예외 처리 중 에러 !! ★★★★★ \r\n" + e.getMessage());
        }
        try {
            if (BatchRunningJobManager.getInstance().isJobRunning(strUUID) == true) BatchRunningJobManager.getInstance().removeRunningJobInfo(strUUID);

        } catch (Exception e) {
            logger.error("{"+logHeader+"} ★★★★★ OutboundSocketHandle JPD 예외 처리 중 에러 !! ★★★★★ \r\n"+ e.getMessage());
        }

        try {
			// = this.context.getExceptionInfo().getException();

            // 파일로그 처리
            String errMsg = ExceptionUtil.getErrorCode(ex, "BECEAIFJC005");
            logger.error("{"+logHeader+"}"+" {"+errMsg+"}"+ ex.getMessage());

            // DB로그 처리
			new JobFinishHandler(batchDoc).handleErrorEnd(errMsg);

        } catch (Exception e) {
            logger.error("{} ★★★★★ OutboundSocketHandle JPD 예외 처리 중 에러 !! ★★★★★ \r\n", logHeader, e);
        }
    }

    
}
