package com.inspect.client.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.inspect.base.core.utils.DateUtils;
import com.inspect.client.domain.ReqDomain;
import com.inspect.client.domain.ResDomain;
import com.inspect.client.mapper.ClientStatisticsMapper;
import com.inspect.client.util.CallDeviceApi;
import com.inspect.base.core.exception.ServiceException;
import com.inspect.base.core.service.SyncDataToUpstreamService;
import com.inspect.base.core.web.domain.AjaxResult;
import com.inspect.maintain.controller.MaintainRegionController;
import com.inspect.partrolresult.controller.PatrolResultController;
import com.inspect.system.base.openDomain.BasedataEqpBookMoMain;
import com.inspect.task.controller.PatrolTaskController;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;

import com.inspect.task.domain.PatrolTask;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class ClientService {
    private final Logger logger = LoggerFactory.getLogger(ClientService.class);
    @Resource
    PatrolTaskController patrolTaskController;
    @Resource
    PatrolResultController patrolResultController;
    @Resource
    MaintainRegionController maintainRegionController;
    @Resource
    ClientStatisticsMapper statisticsMapper;
    public int[] taskTypeArray = new int[]{101, 102, 81, 41, 61};
    public int[] queryTypeArray = new int[]{121};
    @Value("${tcp.client.lowMsg}")
    public String lowMsgUrl;
    @Resource
    SyncDataToUpstreamService syncDataToUpstreamService;
    public static HashMap<String, String> modelMap = new HashMap<>();

    private final ExecutorService threadPool = new ThreadPoolExecutor(
            2, 4, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(4));

    public static void initModelMap() {
        modelMap.put("1", "host_file_path");
        modelMap.put("2", "robot_file_path");
        modelMap.put("3", "video_file_path");
        modelMap.put("4", "device_file_path");
        modelMap.put("5", "drone_file_path");
        modelMap.put("6", "voice_file_path");
        modelMap.put("7", "task_file_path");
        modelMap.put("8", "overhaularea_file_path");
        modelMap.put("9", "map_file_path");
    }

    public AjaxResult handleLowMsg(JSONObject jsonObject) {
        int type = jsonObject.getInteger("Type");
        String msg = jsonObject.toJSONString();
        logger.info("CLIENT 处理上级系统下发消息, type: {}, 内容：{}", type, msg);
        String result = null;
        String deviceCode;
        if (Arrays.contains(taskTypeArray, type)) {
            deviceCode = jsonObject.getString("Command");
            switch (type) {
                case 41:
                    PatrolTask patrolTask = new PatrolTask();
                    patrolTask.setTaskCode(jsonObject.getString("Code"));
                    patrolTask.setExecutionStatus(deviceCode);
                    patrolTaskController.sendJQR(patrolTask);
                    break;
                case 61:
                    try {
                        logger.info("使用线程池处理模型数据请求");
                        threadPool.execute(new Runnable() {
                            @Override
                            public void run() {
                                logger.info("开始收集模型数据");
                                BasedataEqpBookMoMain basedataEqpbookMomain = new BasedataEqpBookMoMain();
                                basedataEqpbookMomain.setType(deviceCode);
                                String eqpBookListInfo = patrolResultController.getEqpBookListInfo(basedataEqpbookMomain);
                                logger.info("CLIENT 处理上级系统下发消息 61, res: {}", eqpBookListInfo);
                                JSONObject parse = JSONObject.parseObject(eqpBookListInfo);
                                JSONObject itemJson = new JSONObject();
                                itemJson.put(modelMap.get(deviceCode), parse.getString(modelMap.get(deviceCode)));
                                String json = itemJson.toJSONString();
                                logger.info("上报模型数据到上级系统");
                                syncDataToUpstreamService.postMessage(json);
                            }
                        });
                        return AjaxResult.success();
                    } catch (Exception e) {
                        logger.error("error", e);
                        return AjaxResult.error();
                    }
                case 81:
                    JSONArray jsonArray = jsonObject.getJSONArray("Items");
                    for (int i = 0; i < jsonArray.size(); ++i) {
                        JSONObject item = jsonArray.getJSONObject(i);
                        item.put("isUp", 1);
                        maintainRegionController.add(item.toJSONString());
                    }

                    return AjaxResult.success("ok", result);
                default:
                    JSONArray array = jsonObject.getJSONArray("Items");
                    for (int i = 0; i < array.size(); ++i) {
                        JSONObject item = array.getJSONObject(i);
                        item.put("isUp", 1);
                        patrolTaskController.add(item.toJSONString());
                    }
            }
        } else if (Arrays.contains(queryTypeArray, type)) {
            result = handleQueryMsg(jsonObject);
        } else {
            deviceCode = jsonObject.getString("Code");
            String iipCode = statisticsMapper.queryIICSystemCode();
            if (StringUtils.isBlank(iipCode)) {
                throw new ServiceException("巡视主机唯一标识未查询到");
            }

            String receiveCodeCode = statisticsMapper.queryPatrolSystemCodeByDeviceCode(deviceCode);
            if (StringUtils.isBlank(receiveCodeCode)) {
                throw new ServiceException(deviceCode + "对应的巡视系统唯一标识未查询到");
            }

            jsonObject.put("SendCode", iipCode);
            jsonObject.put("ReceiveCode", receiveCodeCode);
            JSONObject jsonObject1 = CallDeviceApi.callDevice(lowMsgUrl, jsonObject.toJSONString());
            if (StringUtils.equals(jsonObject1.getString("code"), "500")) {
                return AjaxResult.fail(500, jsonObject1.getString("msg"));
            }
        }

        return AjaxResult.success("ok", result);
    }

    public String handleQueryMsg(JSONObject jsonObject) {
        Integer command = jsonObject.getInteger("Command");
        ReqDomain reqDomain = new ReqDomain();
        JSONArray items = jsonObject.getJSONArray("Items");
        JSONObject job = items.getJSONObject(0);
        reqDomain.setBeginTime(job.getString("begin_time"));
        reqDomain.setEndTime(job.getString("end_time"));
        ResDomain resDomain = null;
        switch (command) {
            case 1:
                resDomain = statisticsMapper.queryTaskDone(reqDomain);
                break;
            case 2:
                resDomain = statisticsMapper.queryPersonExamine(reqDomain);
                break;
            case 3:
                resDomain = statisticsMapper.queryWarning(reqDomain);
                break;
            case 4:
                resDomain = statisticsMapper.queryResultPersonExamine(reqDomain);
                break;
            case 5:
                resDomain = statisticsMapper.queryPointNum(reqDomain);
                break;
            default:
                logger.warn("类型：{},不在处理范围内，不予处理", command);
        }

        resDomain = handlePercent(resDomain);
        String json = JSONObject.toJSONString(resDomain);
        return json;
    }

    public ResDomain handlePercent(ResDomain resDomain) {
        Integer totalNum = resDomain.getTotalNum();
        Integer validNum = resDomain.getValidNum();
        if (null != totalNum && validNum != null) {
            BigDecimal validDecimal = BigDecimal.valueOf((long) validNum);
            BigDecimal totalDecimal = BigDecimal.valueOf((long) totalNum);
            BigDecimal divide = validDecimal.divide(totalDecimal, 3, 4);
            resDomain.setPercent(this.handlePercent(divide));
            return resDomain;
        } else {
            if (null == totalNum) {
                resDomain.setTotalNum(0);
            }

            if (null == validNum) {
                resDomain.setValidNum(0);
            }

            if (resDomain.getTotalNum() == 0 || resDomain.getValidNum() == 0) {
                resDomain.setPercent(handlePercent(BigDecimal.ZERO));
            }

            return resDomain;
        }
    }

    public String handlePercent(BigDecimal num) {
        if (null != num && !num.equals(BigDecimal.ZERO)) {
            num.setScale(3, 4);
            return num.toPlainString() + "%";
        } else {
            return "0.000%";
        }
    }

    public JSONObject callDeviceCommand(String msg) {
        JSONObject jsonObject = JSONObject.parseObject(msg);
        logger.info("[CLIENT] callDeviceCommand jsonObject: {}", jsonObject.toString());
        Integer type = jsonObject.getInteger("Type");
        if (type == 61) {
            String stationNo = statisticsMapper.selectStationNo();
            if (StringUtils.isNotBlank(stationNo)) {
                jsonObject.put("Code", stationNo);
            }

            String iipCode = statisticsMapper.queryIICSystemCode();
            if (StringUtils.isBlank(iipCode)) {
                throw new ServiceException("巡视主机唯一标识未查询到");
            }
            jsonObject.put("SendCode", iipCode);

            try {
                String receiveCode = jsonObject.getString("ReceiveCode");
                if(StringUtils.isNotEmpty(receiveCode)) {
                    if (receiveCode.startsWith("areaPatrolServer")) {
                        logger.info("[CLIENT] 许继边缘节点ReceiveCode: {}, lowMsgUrl: {}", receiveCode, lowMsgUrl);
                        jsonObject.computeIfAbsent("Time", k -> DateUtils.format(DateUtils.yyyyMMddHHmmss2, new Date()));
                        jsonObject.put("Command", "4");//边缘节点点位同步命令为4
                        jsonObject.put("ReceiveCode",receiveCode);
                        logger.info("--------------[CLIENT] 许继边缘节点点位同步jsonObject: {}", jsonObject.toJSONString());
                    } else {
                        logger.info("[CLIENT] 直连设备ReceiveCode: {}, lowMsgUrl: {}", receiveCode, lowMsgUrl);
                        jsonObject.computeIfAbsent("Time", k -> DateUtils.format(DateUtils.yyyyMMddHHmmss2, new Date()));
                        jsonObject.put("Command", "1");//直连设备点位同步命令为1
                        jsonObject.put("ReceiveCode",receiveCode);
                        logger.info("--------------[CLIENT] 直连设备点位同步jsonObject: {}", jsonObject.toJSONString());
                    }
                    return CallDeviceApi.callDevice(lowMsgUrl, jsonObject.toJSONString());
                } else {
                    throw new ServiceException("receiveCode is empty");
                }
            } catch (Exception e) {
                throw new ServiceException("Call " + lowMsgUrl + " Exception!");
            }


//            String robotSystemCode = statisticsMapper.queryRobotSystemCode();
//            if (StringUtils.isBlank(robotSystemCode)) {
//                logger.error("机器人巡视系统唯一标识未查询到");
//                robotSystemCode = "";
//            }
//
//            jsonObject.put("ReceiveCode", robotSystemCode);
//            String nestSystemCode = statisticsMapper.queryNestSystemCode();
//            if (StringUtils.isBlank(nestSystemCode)) {
//                throw new ServiceException("机器人巡视系统唯一标识未查询到");
//            } else {
//                try {
//                    logger.info("[CLIENT] nestSystemCode: {}, lowMsgUrl: {}", nestSystemCode, lowMsgUrl);
//                    jsonObject.put("ReceiveCode", nestSystemCode);
//                    jsonObject.computeIfAbsent("Time", k -> DateUtils.format(DateUtils.yyyyMMddHHmmss2, new Date()));
//
//                    return CallDeviceApi.callDevice(lowMsgUrl, jsonObject.toJSONString());
//                } catch (Exception e) {
//                    throw new ServiceException("Call " + lowMsgUrl + " Exception!");
//                }
//            }
        } else {
            try {
                return CallDeviceApi.callDevice(lowMsgUrl, msg);
            } catch (Exception e) {
                throw new ServiceException("Call " + lowMsgUrl + " Exception 2!");
            }
        }
    }

    static {
        initModelMap();
    }
}
