package org.wcs.plugin.plc;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.wcs.constant.enums.database.PlcTypeEnum;
import org.wcs.mapper.intf.AppBasePlcService;
import org.wcs.model.bo.tuple.Tuple3;
import org.wcs.model.po.app.AppBasePlc;
import org.wcs.plugin.plc.common.PlcCommonData;
import org.wcs.plugin.plc.communication.IPlcCommunication;
import org.wcs.plugin.plc.communication.PlcSiemensCommunication;
import org.wcs.plugin.plc.model.SiemensDBAddress;
import org.wcs.utils.AppStringUtils;
import org.wcs.utils.SpringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PlcCommunicationFactory {


    /**
     * PLC通讯对象 <PLC类型，PLC通讯类>
     */
    private static Map<Integer, IPlcCommunication> plcCommunicationMap;

    /**
     * PLCID <PLCID，PLC类型>
     */
    private static Map<Integer, Integer> plcIdMap;



    /**
     * 注册PLC
     */
    public static void registerPlcCommunication() {
        setPlcCommunicationMap(); // 加载PLC通讯对象
        setPlcIdMap(); // 加载PLCID和PLC类型的对应关系
    }

    /**
     * 通过PLC类型获取PLC通讯对象
     *
     * @param plcType PLC类型
     * @return PLC通讯对象 --- 若不存在则返回西门子方法
     */
    public static IPlcCommunication getPlcCommunicationByPlcType(Integer plcType) {
        registerPlcCommunication();
        IPlcCommunication iPlcCommunication;
        if (plcCommunicationMap.containsKey(plcType)) {
            iPlcCommunication = plcCommunicationMap.get(plcType);
        } else {
            iPlcCommunication = new PlcSiemensCommunication();
        }
        iPlcCommunication.initialize(); // 调用初始化方法
        return iPlcCommunication;
    }

    /**
     * 通过PLCID获取PLC通讯对象
     *
     * @param plcId PLCID
     * @return PLC通讯对象 --- 若不存在则返回西门子方法
     */
    public static IPlcCommunication getPlcCommunicationByPlcId(Integer plcId) {
        registerPlcCommunication();
        if(plcId == null) {
            return getPlcCommunicationByPlcType(PlcTypeEnum.SIEMENS.getCode());
        }
        if(plcIdMap.containsKey(plcId)) {
            return getPlcCommunicationByPlcType(plcIdMap.get(plcId));
        }
        return getPlcCommunicationByPlcType(PlcTypeEnum.SIEMENS.getCode());
    }


    /**
     * 获取西门子方法
     *
     * @return 西门子方法
     */
    public static IPlcCommunication siemens() {
        return getPlcCommunicationByPlcType(PlcTypeEnum.SIEMENS.getCode());
    }


    /* ****************************** 初始化时加载数据方法 ************************************** */

    /**
     * 加载PLC通讯对象
     */
    private static void setPlcCommunicationMap() {
        if(plcCommunicationMap == null) {
            plcCommunicationMap = new HashMap<>();
        }
        if(!plcCommunicationMap.isEmpty()) {
            return;
        }
        // 添加西门子方法
        IPlcCommunication plcCommunication = new PlcSiemensCommunication();
        plcCommunicationMap.put(PlcTypeEnum.SIEMENS.getCode(), plcCommunication);
    }

    /**
     * 加载PLCID
     */
    private static void setPlcIdMap() {
        if(plcIdMap == null) {
            plcIdMap = new HashMap<>();
        }
        if(!plcIdMap.isEmpty()) {
            return;
        }
        AppBasePlcService bean = SpringUtils.getBean(AppBasePlcService.class);
        List<AppBasePlc> basePlcs = bean.queryAll();
        if(basePlcs == null) {
            return;
        }
        if(basePlcs.isEmpty()) {
            plcIdMap.put(0, 0);
            return;
        }
        for (AppBasePlc basePlc : basePlcs) {
            plcIdMap.put(basePlc.getPlcId(), basePlc.getPlcType());
        }
    }

    /* ****************************** 初始化时加载数据方法 END ************************************** */



}
