package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.busi.collect;

import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 采集工位节拍调度单例模式
 */
@Slf4j
public class SxCellTaktDispatchSingleton {

    protected volatile static Boolean isInit = false;

    private static class SxCellTaktDispatchHolder { private final static SxCellTaktDispatchSingleton INSTANCE = new SxCellTaktDispatchSingleton(); }

    public static SxCellTaktDispatchSingleton getInstance() { return SxCellTaktDispatchHolder.INSTANCE; }

    private SxCellTaktDispatchSingleton() { isInit = true; }

    private volatile static Map<String, SxCellTaktMonitorHandler> cellTaktMonitorMap = new ConcurrentHashMap<>();

    public static Boolean getIsInit() { return isInit; }

    public static synchronized void execMonitor(String org, Map<String, String> cfgMap) {
        if (CollectionUtils.isEmpty(cfgMap)) execMonitorRemove(org, getCellTaktMonitorMapKeyList(org));
        else execMonitorCompareToCfg(org, cfgMap);
    }

    private static void execMonitorRemove(String org, List<String> removeKeyList) {
        log.info("工厂{}第三方PLC数据采集 --- {} STRATEGY EXEC SINGLETON --- MONITOR CLOSED KEY:{} --- START ---", org, MesPcnExtConstWords.COLLECT_CELL_TAKT, CollectionUtils.isEmpty(removeKeyList) ? MesPcnExtConstWords.EMPTY : JSONObject.toJSONString(removeKeyList));
        if (!CollectionUtils.isEmpty(removeKeyList)) removeKeyList.stream().forEach(SxCellTaktDispatchSingleton::execMonitorRemove);
    }

    private static void execMonitorCompareToCfg(String org, Map<String, String> cfgMap) {
        List<String> cellTaktMonitorMapKeyList = getCellTaktMonitorMapKeyList(org);
        List<String> removeKeyList = CollectionUtils.isEmpty(cellTaktMonitorMapKeyList) ? null : cellTaktMonitorMapKeyList.stream().filter(o -> (!StringUtils.isEmpty(o) && !cfgMap.containsKey(o))).collect(Collectors.toList());
        execMonitorRemove(org, removeKeyList);
        execMonitorCompute(org, cfgMap);
    }

    private static List<String> getCellTaktMonitorMapKeyList(String org) {
        List<String> cellTaktMonitorMapKeyList = CollectionUtils.isEmpty(cellTaktMonitorMap) ? null : new ArrayList<>(cellTaktMonitorMap.keySet());
        return CollectionUtils.isEmpty(cellTaktMonitorMapKeyList) ? null : cellTaktMonitorMapKeyList.stream().filter(o -> (!StringUtils.isEmpty(o) && o.split(MesPcnExtConstWords.COLON)[1].equals(org))).collect(Collectors.toList());
    }

    private static void execMonitorRemove(String key) {
        SxCellTaktMonitorHandler handler = cellTaktMonitorMap.get(key);
        handler.cancel();
        cellTaktMonitorMap.remove(key);
        log.info("工厂{}第三方PLC数据采集 --- {} STRATEGY EXEC SINGLETON --- MONITOR CLOSED KEY:[{}] ---", key.split(MesPcnExtConstWords.COLON)[1], MesPcnExtConstWords.COLLECT_CELL_TAKT, key);
    }

    private static void execMonitorCompute(String org, Map<String, String> cfgMap) {
        for (String key : cfgMap.keySet()) {
            if (StringUtils.isEmpty(key)) continue;
            String[] plcCodeArr = cfgMap.get(key).split(MesPcnExtConstWords.COMMA);
            if (null == plcCodeArr || plcCodeArr.length != 2) continue;
            SxCellTaktMonitorHandler handler = cellTaktMonitorMap.computeIfAbsent(key, o -> new SxCellTaktMonitorHandler(org, key));
            handler.isRetry(plcCodeArr);
            log.info("工厂{}第三方PLC数据采集 --- {} STRATEGY EXEC SINGLETON --- MONITOR {} KEY:[{}] ---", org, MesPcnExtConstWords.COLLECT_CELL_TAKT, handler.version() ? "ADD" : "RETRY", key);
        }
    }

}
