package kr.gmtc.gw.comp.rest;

import java.io.IOException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import kr.gmtc.gw.comp.rest.vo.RestServiceData;
import kr.gmtc.gw.comp.thread.CustomThread;
import kr.gmtc.gw.standstatus.utils.CmmnUtil;

public class ServiceQueManager {
    
    HashMap<Integer, Queue<RestServiceData>> serviceQueue;
    Map<Integer, LinkedList<RestServiceData>> serviceList;

    private boolean serviceRunnig = false;
    private Integer scvQcount;
    private Integer scvQmaxCount;
    private Integer scvQdiffTime;
    private Integer scvQclearTime;

    private CustomThread serviceQClearThread;

    protected Logger logger;

    public ServiceQueManager(Map<Integer, LinkedList<RestServiceData>> serviceList, boolean serviceRunnig){

        this.serviceList = serviceList;
        this.serviceRunnig = serviceRunnig;

        logger = LoggerFactory.getLogger(this.getClass());

         // 업무 스레드 생성, 대기 없이 무한반복
        serviceQClearThread = new CustomThread("serviceQClearThread", this, CustomThread.NO_SLEEP, this::serviceQClear, null, false);
    }

    public void start(){

         // 전송용 Queue 생성
        createList();

        //serviceQClearThread.start();

    }

    // 설정에따라 REST용 서비스 큐 생성
    @SuppressWarnings("unchecked")
    public void createQueue() {

        // String className = "java.util.Queue";
        //Class cls = Class.forName(className);
        
        for(int idx=0; idx<scvQcount; idx++) {

            Queue<RestServiceData> obj = null;

            try {

                obj = (Queue<RestServiceData>) java.util.LinkedList.class.newInstance();

            } catch (InstantiationException e) {
                logger.error("[ServiceQueManager] createQueue-InstantiationException : " + CmmnUtil.getStatckTrace(e));
            } catch (IllegalAccessException e) {
                logger.error("[ServiceQueManager] createQueue-IllegalAccessException : " + CmmnUtil.getStatckTrace(e));
            }

            serviceQueue.put(idx, obj);

        }

    }

    @SuppressWarnings("unchecked")
    public void createList() {

        // String className = "java.util.Queue";
        //Class cls = Class.forName(className);
        
        for(int idx=0; idx<scvQcount; idx++) {

            LinkedList<RestServiceData> obj = null;

            try {

                obj = (LinkedList<RestServiceData>) java.util.LinkedList.class.newInstance();

            } catch (InstantiationException e) {
                logger.error("[ServiceQueManager] createQueue-InstantiationException : " + CmmnUtil.getStatckTrace(e));
            } catch (IllegalAccessException e) {
                logger.error("[ServiceQueManager] createQueue-IllegalAccessException : " + CmmnUtil.getStatckTrace(e));
            }

            serviceList.put(idx, obj);

        }

    }

    private void serviceQClear() throws InterruptedException, IOException {

        String sRecvTime = "";

        RestServiceData jsonData;

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");

        LocalDateTime dateTime;

        int iQcnt = 0;

        if(serviceRunnig) return;

        try {

            for(int idx=0; idx<scvQcount; idx++) {

                iQcnt = serviceQueue.get(idx).size();

                if (iQcnt > scvQmaxCount  ) {

                    jsonData = serviceQueue.get(idx).peek();

                    // sRecvTime = jsonData.getRecptn_dt();

                    dateTime = LocalDateTime.parse(sRecvTime, formatter);

                    Duration diff = Duration.between(dateTime, LocalDateTime.now());

                    if( scvQclearTime > 0 && diff.toMillis() > scvQclearTime) { // 일정시간 미사용으로 판단
                        serviceQueue.get(idx).clear();
                        logger.info("[MainController] serviceQClear : " + (idx +1) +"번 Queue 장기 미사용으로 초기화 (" + iQcnt +"건), 설정시간:" + scvQclearTime);
                    }
                    else if( diff.toMillis() > scvQdiffTime) { // 데이터 과적재

                        iQcnt = serviceQueue.get(idx).size();
                        int iPollCnt = iQcnt - scvQmaxCount;

                        while (iQcnt - scvQmaxCount >= 0) {
                            serviceQueue.get(idx).poll();
                            iQcnt--;
                            
                        }

                        logger.info("[MainController] serviceQpoll : " + (idx +1) +"번 Queue 일부 버림 (" + iPollCnt +"건), 설정시간:" + scvQdiffTime + " 설정건수:"+ scvQmaxCount);
                    }
                }
            }


            Thread.sleep(1000);
        } catch (InterruptedException e) {
            logger.error("[MainController] serviceQClear-InterruptedException : " + CmmnUtil.getStatckTrace(e));

        } catch (Exception e) {
            logger.error("[MainController] serviceQClear-Exception : " + CmmnUtil.getStatckTrace(e) + ">> " + sRecvTime.toString() );
        }
    }

    public void setScvQcount(Integer scvQcount) {
        this.scvQcount = scvQcount;
    }

    public void setScvQmaxCount(Integer scvQmaxCount) {
        this.scvQmaxCount = scvQmaxCount;
    }

    public void setScvQdiffTime(Integer scvQdiffTime) {
        this.scvQdiffTime = scvQdiffTime;
    }

    public void setScvQclearTime(Integer scvQclearTime) {
        this.scvQclearTime = scvQclearTime;
    }


    

    
}
