package com.cisdi.data.DHV;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cisdi.data.DHV.gateway.vo.dhv.OtherParamVO;
import com.cisdi.data.common.exception.BusinessException;
import com.cisdi.data.sdk.consts.ServiceName;
import com.cisdi.data.sdk.enums.GatewayState;
import com.cisdi.data.sdk.gateway.base.PulledHttpGatewayBase;
import com.cisdi.data.sdk.param.PullHttpParam;
import com.cisdi.data.sdk.procotol.message.HttpReturnMessage;
import com.cisdi.data.sdk.service.RouteService;
import com.cisdi.data.sdk.vo.DeviceVo;
import com.cisdi.data.sdk.vo.ExeResultVo;
import com.cisdi.data.DHV.gateway.impl.dhv.YFDHVPullTask;
import com.cisdi.data.DHV.gateway.vo.PullHttpTaskStartVo;
import com.cisdi.data.DHV.gateway.vo.dhv.MPSVO;
import com.cisdi.data.DHV.gateway.vo.dhv.MPVVO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author jianghc
 * @function: YFDHealthVibrationGateway永锋现场-设备健康振动数据接入网关，入口
 * @date 2022年05月05日 09:29
 */
public class YFDHealthVibrationGateway extends PulledHttpGatewayBase {
    private static Logger logger = LoggerFactory.getLogger(YFDHealthVibrationGateway.class);

    //设备id
    private String deviceId;
    //设备当前是否运行
    private AtomicBoolean shouldRun = null;
    // 允许最小的拉取间隔为1毫秒
    private static final int Min_Pull_Internal = 1;
    // 允许最小的超时时间间隔，为1000毫秒
    private static final int Min_Timeout = 1000;


    @Override
    public ExeResultVo sendReturnMessage(HttpReturnMessage httpReturnMessage) {
        return null;
    }

    @Override
    public void start() {
        if (state == GatewayState.RUNNING) {
            return;
        }
        try {
            startInternal();
            state = GatewayState.RUNNING;
            logger.info("永峰设备健康振动数据http拉取网关:{}启动成功", instanceVo.getRunId());
        } catch (Exception e) {
            logger.error("永峰设备健康振动数据http拉取网关:{}启动失败", instanceVo.getRunId());
            logger.error(e.getLocalizedMessage(), e);
        }
    }

    private void startInternal() {
        httpParam = JSON.parseObject(instanceVo.getParameter(), PullHttpParam.class);

        if (StringUtils.isEmpty(httpParam.getPullLocation())) {
            throw new BusinessException("未正确配置拉取地址。");
        }

        if (httpParam.getPullInternal() == null) {
            throw new BusinessException("未正确配置拉取间隔");
        }

        if (httpParam.getTimeout() == null) {
            throw new BusinessException("未正确配置拉取超时时间");
        }

        httpParam.setPullInternal(httpParam.getPullInternal() < Min_Pull_Internal ?
                Min_Pull_Internal : httpParam.getPullInternal());

        httpParam.setTimeout(httpParam.getTimeout() < Min_Timeout ? Min_Timeout : httpParam.getTimeout());

        RouteService routeService = (RouteService) serviceProvider.getByName(ServiceName.Route);
        List<DeviceVo> deviceVos = routeService.findByRunId(instanceVo.getRunId());

        if (deviceVos.size() > 1) {
            throw new BusinessException("网关Id:" + instanceVo.getRunId() + "为永峰设备健康振动数据http拉取网关，只允许关联一个设备Id");
        }

        deviceId = deviceVos.size() > 0 ? deviceVos.get(0).getDeviceId() : null;

        logger.info("永峰设备健康振动数据http拉取网关:{}读取启动配置参数:{}", getInstanceVo().getRunId(), httpParam);

        closePrevState();
        shouldRun = new AtomicBoolean(true);

//        DynamicCodecService dynamicCodecService = (DynamicCodecService) serviceProvider.getByName(ServiceName.DynamicCodec);
//        if (dynamicCodecService == null || !(dynamicCodecService instanceof DynamicCodecService)) {
//            throw new BusinessException("获取JDynamicCodecService失败");
//        }
//        String tagConfig = dynamicCodecService.findByRunIdAndMsgKeyNoCache(getInstanceVo().getRunId(),"mps.MPS");
//        if (Strings.isEmpty(tagConfig)) {
//            throw new BusinessException("未正确配置当前DHV所需配置");
//        }else{
//            logger.info("点位配置信息："+tagConfig);
//        }


        // 启动线程
        PullHttpTaskStartVo startVo = new PullHttpTaskStartVo();
        startVo.setDeviceId(deviceId);
        startVo.setGatewayBase(this);
        startVo.setServiceProvider(serviceProvider);
        startVo.setHttpParam(httpParam);
        startVo.setShouldRun(shouldRun);

        //其他参数
        OtherParamVO otherParamVO = null;
        if (httpParam.getOtherParameter() != null && httpParam.getOtherParameter().trim().length() > 0) {
            String otherParameter = httpParam.getOtherParameter();
            otherParamVO = parseOtherParameter(otherParameter);
        } else {
            throw new BusinessException("永峰设备健康振动数据Http网关其他参数配置异常!");
        }

        // 启动拉取ids的线程
        YFDHVPullTask idsTask = new YFDHVPullTask(startVo, otherParamVO);
        Thread idsThread = new Thread(idsTask, "永峰-设备健康振动数据网关");
        idsThread.start();

        state = GatewayState.RUNNING;
    }

    /**
     * @param otherParameter
     * @return com.cisdi.data.yongfeng.gateway.vo.dhv.OtherParamVO
     * @function: 解析其他参数
     * @author jianghc
     * @date 2022/5/6 16:41
     */
    private OtherParamVO parseOtherParameter(String otherParameter) {
        MPSVO mpsvo = new MPSVO();
        List<MPVVO> mpvvoList = new ArrayList<>();
        JSONObject jsonObject = null;
        try {
            jsonObject = JSONObject.parseObject(otherParameter);
        } catch (Exception ex) {
            throw new BusinessException("永峰设备健康振动数据Http网关其他参数配置异常!");
        }
        Object obj = jsonObject.get("mps");
        if (obj != null && obj instanceof JSONObject) {
            JSONObject databaseName = (JSONObject) obj;
            Object dbNames = databaseName.get("databaseName");
            if (dbNames instanceof JSONArray) {
                JSONArray jsonArray = (JSONArray) dbNames;
                List<String> dbNameList = new ArrayList<>();
                for (int i = 0; i < jsonArray.size(); i++) {
                    dbNameList.add((String) jsonArray.get(i));
                }
                mpsvo.setDatabaseName(dbNameList);
            } else if (dbNames instanceof String) {
                List<String> dbNameList = new ArrayList<>();
                dbNameList.add((String) dbNames);
                mpsvo.setDatabaseName(dbNameList);
            }
        }
        Object obj1 = jsonObject.get("mpv");
        if (obj1 != null && obj1 instanceof JSONArray) {
            JSONArray jsonArray = (JSONArray) obj1;
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject obj2 = (JSONObject) jsonArray.get(i);
                MPVVO mpvvo = new MPVVO();
                String databaseName = obj2.getString("databaseName");
                if (databaseName != null && databaseName.trim().length() > 0) {
                    mpvvo.setDatabaseName(databaseName);
                } else {
                    mpvvo.setDatabaseName(null);
                }
                String measuringPointNumberOrTechID = obj2.getString("measuringPointNumberOrTechID");
                if (measuringPointNumberOrTechID != null && measuringPointNumberOrTechID.trim().length() > 0) {
                    mpvvo.setMeasuringPointNumberOrTechID(measuringPointNumberOrTechID);
                } else {
                    if (databaseName != null && databaseName.trim().length() > 0) {
                        throw new BusinessException("永峰设备健康振动数据Http网关其他参数配置异常!");
                    }
                    mpvvo.setMeasuringPointNumberOrTechID(null);
                }
                String assignmentTechIDorName = obj2.getString("assignmentTechIDorName");
                if (assignmentTechIDorName != null && assignmentTechIDorName.trim().length() > 0) {
                    mpvvo.setAssignmentTechIDorName(assignmentTechIDorName);
                } else {
                    if (databaseName != null && databaseName.trim().length() > 0) {
                        throw new BusinessException("永峰设备健康振动数据Http网关其他参数配置异常!");
                    }
                    mpvvo.setAssignmentTechIDorName(null);
                }
                Boolean ShortMem = obj2.getBoolean("ShortMem");
                if (ShortMem != null && ShortMem.equals(Boolean.TRUE)) {
                    mpvvo.setShortMem(Boolean.TRUE);
                } else if (ShortMem != null && ShortMem.equals(Boolean.FALSE)) {
                    mpvvo.setShortMem(Boolean.FALSE);
                } else {
                    mpvvo.setShortMem(null);
                }
                mpvvo.setMaxCount(obj2.getInteger("MaxCount"));
                Boolean LongMem = obj2.getBoolean("LongMem");
                if (LongMem != null && LongMem.equals(Boolean.TRUE)) {
                    mpvvo.setLongMem(Boolean.TRUE);
                } else if (LongMem != null && LongMem.equals(Boolean.FALSE)) {
                    mpvvo.setLongMem(Boolean.FALSE);
                } else {
                    mpvvo.setLongMem(null);
                }
                String StartDateTime = obj2.getString("StartDateTime");
                if (StartDateTime != null && StartDateTime.trim().length() > 0) {
                    mpvvo.setStartDateTime(StartDateTime);
                } else {
                    mpvvo.setStartDateTime(null);
                }
                String StopDateTime = obj2.getString("StopDateTime");
                if (StopDateTime != null && StopDateTime.trim().length() > 0) {
                    mpvvo.setStopDateTime(StopDateTime);
                } else {
                    mpvvo.setStopDateTime(null);
                }
                mpvvo.setMpktTech(obj2.getInteger("MpktTech"));
                String Expand = obj2.getString("Expand");
                if (Expand != null && Expand.trim().length() > 0) {
                    mpvvo.setExpand(Expand);
                } else {
                    mpvvo.setExpand(null);
                }
                mpvvoList.add(mpvvo);
            }
        } else if (obj1 != null && obj1 instanceof JSONObject) {
            JSONObject obj2 = (JSONObject) obj1;
            MPVVO mpvvo = new MPVVO();
            String databaseName = obj2.getString("databaseName");
            if (databaseName != null && databaseName.trim().length() > 0) {
                mpvvo.setDatabaseName(databaseName);
            } else {
                mpvvo.setDatabaseName(null);
            }
            String measuringPointNumberOrTechID = obj2.getString("measuringPointNumberOrTechID");
            if (measuringPointNumberOrTechID != null && measuringPointNumberOrTechID.trim().length() > 0) {
                mpvvo.setMeasuringPointNumberOrTechID(measuringPointNumberOrTechID);
            } else {
                if (databaseName != null && databaseName.trim().length() > 0) {
                    throw new BusinessException("永峰设备健康振动数据Http网关其他参数配置异常!");
                }
                mpvvo.setMeasuringPointNumberOrTechID(null);
            }
            String assignmentTechIDorName = obj2.getString("assignmentTechIDorName");
            if (assignmentTechIDorName != null && assignmentTechIDorName.trim().length() > 0) {
                mpvvo.setAssignmentTechIDorName(assignmentTechIDorName);
            } else {
                if (databaseName != null && databaseName.trim().length() > 0) {
                    throw new BusinessException("永峰设备健康振动数据Http网关其他参数配置异常!");
                }
                mpvvo.setAssignmentTechIDorName(null);
            }
            Boolean ShortMem = obj2.getBoolean("ShortMem");
            if (ShortMem != null && ShortMem.equals(Boolean.TRUE)) {
                mpvvo.setShortMem(Boolean.TRUE);
            } else if (ShortMem != null && ShortMem.equals(Boolean.FALSE)) {
                mpvvo.setShortMem(Boolean.FALSE);
            } else {
                mpvvo.setShortMem(null);
            }
            mpvvo.setMaxCount(obj2.getInteger("MaxCount"));
            Boolean LongMem = obj2.getBoolean("LongMem");
            if (LongMem != null && LongMem.equals(Boolean.TRUE)) {
                mpvvo.setLongMem(Boolean.TRUE);
            } else if (LongMem != null && LongMem.equals(Boolean.FALSE)) {
                mpvvo.setLongMem(Boolean.FALSE);
            } else {
                mpvvo.setLongMem(null);
            }
            String StartDateTime = obj2.getString("StartDateTime");
            if (StartDateTime != null && StartDateTime.trim().length() > 0) {
                mpvvo.setStartDateTime(StartDateTime);
            } else {
                mpvvo.setStartDateTime(null);
            }
            String StopDateTime = obj2.getString("StopDateTime");
            if (StopDateTime != null && StopDateTime.trim().length() > 0) {
                mpvvo.setStopDateTime(StopDateTime);
            } else {
                mpvvo.setStopDateTime(null);
            }
            mpvvo.setMpktTech(obj2.getInteger("MpktTech"));
            String Expand = obj2.getString("Expand");
            if (Expand != null && Expand.trim().length() > 0) {
                mpvvo.setExpand(Expand);
            } else {
                mpvvo.setExpand(null);
            }
            mpvvoList.add(mpvvo);
        }
        if ((mpsvo.getDatabaseName() == null || mpsvo.getDatabaseName().size() < 1) && (mpvvoList.size() < 1)) {
            throw new BusinessException("永峰设备健康振动数据Http网关其他参数配置异常!");
        }
        String user = jsonObject.getString("user");
        String pass = jsonObject.getString("pass");
        String Authorization = null;
        if (user != null) {
            Authorization = "Basic " + new String(Base64.getEncoder().encode((user + ":" + pass).getBytes(StandardCharsets.UTF_8)));
        } else {
            Authorization = "Basic ";
        }
        String emptyanddefault = jsonObject.getString("emptyanddefault");
        OtherParamVO otherParamVO = new OtherParamVO();
        otherParamVO.setMpsvo(mpsvo);
        otherParamVO.setMpvvoList(mpvvoList);
        otherParamVO.setAuthorization(Authorization);
        otherParamVO.setEmptyanddefault(emptyanddefault);
        return otherParamVO;
    }

    @Override
    public void shutdown() {
        if (state == GatewayState.CLOSED) {
            return;
        }

        closePrevState();

        logger.info("永峰设备健康振动数据http拉取网关:{}关闭中", getInstanceVo().getRunId());

        state = GatewayState.CLOSED;

        logger.info("永峰设备健康振动数据http拉取网关:{}关闭成功", getInstanceVo().getRunId());
    }

    private void closePrevState() {
        if (shouldRun != null) {
            shouldRun.set(false);
            shouldRun = null;
        }
    }

    @Override
    public Set<String> getActiveDeviceIds() {
        Set<String> set = new HashSet<String>();
        if (deviceId != null) {
            set.add(deviceId);
        }
        return set;
    }

}
