package com.eactive.eai.batch.running;

import java.net.Socket;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;


import com.eactive.eai.adapter.socket.service.SocketService;
import com.eactive.eai.batch.doc.BatchDoc;
import com.eactive.eai.common.util.DatetimeUtil;
import com.eactive.eai.common.util.Logger;

public class BatchRunningJobManager
{

    //파일로거
    private static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);

    private static BatchRunningJobManager instance = new BatchRunningJobManager();

    public static BatchRunningJobManager getInstance() {
        return instance;
    }

    private HashMap<String, SocketService> mapSocketService;  //실시간 연결소켓 객체 (요구송수신,응답송수신 통합)
    private HashMap<String, BatchDoc> mapBatchDoc;            //실시간 BatchDoc 객체 (요구송수신,응답송수신 통합)

    private BatchRunningJobManager() {
        mapSocketService = new HashMap<String, SocketService>();
        mapBatchDoc      = new HashMap<String, BatchDoc>();
    }

    public synchronized void addRunningJobInfo(String strUUID, SocketService service, BatchDoc batchDoc) {
        mapSocketService.put(strUUID, service);
        mapBatchDoc     .put(strUUID, batchDoc);
        printAllRunningJob();
    }

    public synchronized void removeRunningJobInfo(String strUUID) {
        mapSocketService.remove(strUUID);
        mapBatchDoc     .remove(strUUID);
        printAllRunningJob();
    }

    public synchronized void updateRunningDocument(String strUUID, BatchDoc batchDoc) {
        mapBatchDoc     .put(strUUID, batchDoc);
    }

    public synchronized SocketService getRunningSocketService(String strUUID) {
        return mapSocketService.get(strUUID);
    }

    public synchronized Socket getRunningSocket(String strUUID) {
        try {
            SocketService service = (SocketService) mapSocketService.get(strUUID);
            if (service == null) return null;

            return service.getCurrentSocket();

        } catch (Exception ex) {
            logger.error("", ex);
            return null;
        }
    }

    public synchronized BatchDoc getRunningDocument(String strUUID) {
        return mapBatchDoc.get(strUUID);
    }

    public synchronized HashMap<String, BatchDoc> getAllRunningDocuments() {
        return mapBatchDoc;
    }

    public synchronized int getRunningJobCount() {
        return mapSocketService.size();
    }

    public synchronized boolean isJobRunning(String strUUID) {
        return (mapSocketService.get(strUUID) == null)? false : true;
    }

    public synchronized boolean isSocketClosed(String strUUID) {
        SocketService service = (SocketService) mapSocketService.get(strUUID);
        if (service == null) return true;
        if (service.getCurrentSocket() == null) return true;
        return service.getCurrentSocket().isClosed();
    }

    public synchronized void closeRunningSocket(String strUUID) {
        SocketService service = (SocketService) mapSocketService.get(strUUID);
        if (service == null) return;
        service.disconnect();
    }

    private synchronized static void printAllRunningJob() {

        try {
            int jobCount = instance.getRunningJobCount();
            logger.info("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz");
            logger.info("■■■■■ 진행중인 일괄전송 작업 건수 : "+ jobCount +" ■■■■■");

            //소켓 생성 시간으로 정렬
            Object[] arrKey = instance.getAllRunningDocuments().keySet().toArray();
            for (int i=0; i<jobCount; i++) {
                if ( instance.getRunningSocketService((String)arrKey[i]) != null ){
                    arrKey[i] = instance.getRunningSocketService((String)arrKey[i]).getFirstActivity() +":"+ (String)arrKey[i];
                }else{
                    arrKey[i] = "null:"+ (String)arrKey[i];
                }
            }
            Arrays.sort(arrKey);

            //각 Running Jog 출력
            for (int i=0; i<arrKey.length; i++) {
                String[] tempArr = ((String)arrKey[i]).split(":");
                String strUUID = tempArr[1];
                BatchDoc batchDoc = instance.getRunningDocument(strUUID);
                SocketService service  = instance.getRunningSocketService(strUUID);
                if ( service != null ){
                    // 소켓연결시각 / UUID / 업무유형 / 업무구분 / 대외기관 / Local IP:Port / Remote IP:Port
                    logger.info("▶ "+ DatetimeUtil.getFormattedDate("yyyy-MM-dd HH:mm:ss.SSS", new Date(service.getFirstActivity()))
                                +" / "+ batchDoc.getBatchMsg().getHeader().getUUID()
                                +" / "+ batchDoc.getBatchMsg().getHeader().getProcessType()
                                +" / "+ batchDoc.getBatchMsg().getHeader().getProcessName()
                                +" / "+ batchDoc.getBatchMsg().getHeader().getInstitutionName()
                                +" / L="+ (service.getCurrentSocket() == null ? ""  : service.getCurrentSocket().getLocalAddress().getHostAddress() +":"+ service.getCurrentSocket().getLocalPort())
                                +" / R="+ (service.getCurrentSocket() == null ? ""  : service.getCurrentSocket().getInetAddress().getHostAddress() +":"+ service.getCurrentSocket().getPort())
                               );
                }else{
                    // UUID / 업무유형 / 업무구분 / 대외기관
                    logger.info("▶ "   + batchDoc.getBatchMsg().getHeader().getUUID()
                                +" / " + batchDoc.getBatchMsg().getHeader().getProcessType()
                                +" / " + batchDoc.getBatchMsg().getHeader().getProcessName()
                                +" / " + batchDoc.getBatchMsg().getHeader().getInstitutionName()
                               );
                }

            }
            logger.info("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz");

        } catch (Exception ex) {
            logger.error("★★★★★ BatchRunningJobManager : 진행중 작업 출력시 오류 발생 !! ★★★★★", ex);
        }
    }
}