
package com.mvc.netty;

import com.mvc.entity.TAiread;
import com.mvc.entity.TPackLog;
import com.mvc.model.TaskSpecialCfgModel;
import com.mvc.model.upgrade.TUpgradePlanDetailModel;
import com.mvc.model.upgrade.TUpgradeResultsModel;
import com.mvc.netty.dealconstant.HandleMsgCode;
import com.mvc.netty.dealconstant.TaskRemoteIdentifier;
import com.mvc.service.ScheduleService;
import com.mvc.service.copy.TAireadService;
import com.mvc.service.copy.TPackLogService;
import com.mvc.service.taizhang.TaskSpecialCfgService;
import com.mvc.service.upgrade.TUpgradePlanService;
import com.mvc.service.upgrade.TUpgradeResultsService;
import com.mvc.utils.StoreBlockingQueue;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.print.DocFlavor;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
public class ParseThread implements Runnable {

    private static Logger log = LoggerFactory.getLogger(ParseThread.class);

    @Resource
    private TAireadService tAireadService;

    @Resource
    private PackageParse packageParse;

    @Resource
    private RegularMessageParser regularMessageParser;

    @Resource
    private ReissueMessageParser reissueMessageParser;

    @Resource
    private TPackLogService tPackLogService;

    @Resource
    private ScheduleService scheduleService;

    @Resource
    private TUpgradePlanService tUpgradePlanService;

    @Resource
    private VersionMessageParser versionMessageParser;

    @Resource
    private TUpgradeResultsService upgradeResultsService;

    @Resource
    private TaskSpecialCfgService taskSpecialCfgService;

    @Override
    public void run() {
        while (true) {
            try {
                FzBaowenModel take = StoreBlockingQueue.baoweoQueue.take();
                System.out.println("------------channel结束解析数据---------------");
                handleQueueData(take);
                take = null;//尝试,立即回收
            } catch (Exception e) {
                e.printStackTrace();
                log.error(e.getMessage());
            }
        }
    }

    /**
     * 处理队列数据
     *
     * @param take
     */
    private void handleQueueData(FzBaowenModel take) {
        if (take.getType() == null) {//通道接收数据不完整
            if (StringUtils.isNotEmpty(take.getVersionInfo())) {//只收到了设备开机主动上报的版本信息
                handleVersionInfo(take);
            }
            return;
        }

        switch (take.getType()) {
            case VIRT_H_31:
                handleMsg_H31(take);
                break;
            case H_32:
                handleMsg_H32(take);
                break;
            case H_36:
                handleMsg_H36(take);
                break;
            case H_52:
                handleMsg_H52(take);
                break;
            case H_EA:
                handleMsg_HEA(take);
                break;
            case H_E6:
                handleMsg_HE6(take);
                break;
            case H_E2:
                handleMsg_HE2(take);
                break;
            default:
                break;
        }
    }

    /**
     * 处理单包定时报
     *
     * @param take
     */
    private void handleMsg_H31(FzBaowenModel take) {
        String msg = take.getBaowen().get(0);
        TPackLog tPackLog = packageParse.parse(msg);

        TAiread tAiread = regularMessageParser.parse(tPackLog, "S");
        tAiread.setRevTime(take.getLastRevTime());
        tAiread.setRandomCode(take.getRandomCode());
        tAireadService.addTAiread(tAiread);
        tPackLog.setPackCount(1);
        tPackLogService.updateTPackLog(tPackLog);
        setDeviceSn(take, tPackLog);
        tPackLogService.savePackLog(tPackLog, take.getLastRevTime());
        //下发任务存储
        if (take.getTaskdownid() != null && take.getPeizhi().size() > 0) {
            TPackLog tPackLog1 = packageParse.parse_remoteCfg(take.getPeizhi().get(0), take.getTaskdownid());
            tPackLogService.savePackLog(tPackLog1, new Date());
            //tPackLogMapper.insert(tPackLog1);
        }
        handleVersionInfo(take);
    }

    /**
     * 处理多包定时报
     *
     * @param take
     */
    private void handleMsg_H32(FzBaowenModel take) {
        try {
            List<String> baowen = take.getBaowen();
            List<TPackLog> logs = new ArrayList<>();
            //logs 入库
            for (int i = 0; i < baowen.size(); i++) {
                TPackLog tlog = packageParse.parse_duobao(baowen.get(i));
                tlog.setFlag("20");
                logs.add(tlog);
            }
            logs.get(0).setRevTime(take.getLastRevTime());
            setDeviceSn(take, logs.get(0));
            scheduleService.handleMsg_duobaoBypackages(logs, take.getRandomCode());
            Date lastRevTime = take.getLastRevTimeMap().containsKey(HandleMsgCode.H_32) ? take.getLastRevTimeMap().get(HandleMsgCode.H_32) : take.getLastRevTime();
            tPackLogService.savePackLog(logs, lastRevTime);
            //下发任务回执的存储
            if (take.getTaskdownid() != null && take.getPeizhi().size() > 0) {
                TPackLog tPackLog1 = packageParse.parse_remoteCfg(take.getPeizhi().get(0), take.getTaskdownid());
                Date he1RevTime = take.getLastRevTimeMap().containsKey(HandleMsgCode.H_E1) ? take.getLastRevTimeMap().get(HandleMsgCode.H_E1) : new Date();
                tPackLogService.savePackLog(tPackLog1, he1RevTime);
            }
            if (take.getTaskReviewPushreplay().size() > 0) {
                log.info("开始解析审核回执：" + take.getTaskReviewPushreplay().get(0));
                TPackLog tPackLog = packageParse.parse_TaskReviewPush(take.getTaskReviewPushreplay().get(0), take.getTaskReviewPush());
                Date he5RevTime = take.getLastRevTimeMap().containsKey(HandleMsgCode.H_E5) ? take.getLastRevTimeMap().get(HandleMsgCode.H_E5) : new Date();
                tPackLogService.savePackLog(tPackLog, he5RevTime);
            }
            //专项配置
            TaskSpecialCfgModel taskSpecialCfgModel = take.getSpecialCfgModel();
            if (taskSpecialCfgModel != null && StringUtils.isNotEmpty(taskSpecialCfgModel.getReplyMessage())) {
                handleSpecialCfg(taskSpecialCfgModel);
            }
            handleVersionInfo(take);
        } catch (Exception e) {
            log.error("handleMsg_H32:" + e.getMessage(), e);
        }
    }

    /**
     * 处理专项回执报文
     *
     * @param taskSpecialCfgModel
     */
    private void handleSpecialCfg(TaskSpecialCfgModel taskSpecialCfgModel) {
        TPackLog tPackLog = packageParse.parse_FrameHeader(taskSpecialCfgModel.getReplyMessage());
        String temp = tPackLog.getMessage();
        tPackLog.setPackCount(tPackLog.getPackIndex());
        tPackLog.setDatatime(tPackLog.getRptTime());
        tPackLog.setOriginmessage(taskSpecialCfgModel.getReplyMessage());
        tPackLogService.savePackLog(tPackLog, new Date());

        String imei = "";
        String deviceSn = "";

        List<String> keys = TaskRemoteIdentifier.keys();

        while (StringUtils.isNotEmpty(temp)) {
            boolean blnFind = false;
            for (String key : keys) {
                if (!temp.toUpperCase().startsWith(key)) {
                    continue;
                }
                TaskRemoteIdentifier identifier = TaskRemoteIdentifier.getElement(key);
                if (identifier == null) {
                    continue;
                }
                blnFind = true;
                temp = identifier.parse(temp);
                if (identifier == TaskRemoteIdentifier.FF38) {
                    imei = identifier.getValue();
                    imei = imei.length() > 15 ? imei.substring(1) : imei;
                } else if (identifier == TaskRemoteIdentifier.FF08) {
                    deviceSn = identifier.getValue();
                    deviceSn = deviceSn.length() > 11 ? deviceSn.substring(0, 11) : deviceSn;
                }
            }
            if (blnFind == false) {
                break;
            }
        }

        log.info("收到配置SN回执：" + taskSpecialCfgModel.getReplyMessage());
        //1:执行成功,2:返回的数据与下发的不匹配
        String flag = imei.equals(taskSpecialCfgModel.getImei()) && deviceSn.equals(taskSpecialCfgModel.getDeviceSn()) ? "1" : "2";
        taskSpecialCfgModel.setFinishedFlag(flag);
        taskSpecialCfgModel.setFinishedTime(new Date());
        taskSpecialCfgService.updateTaskSpecialCfg(taskSpecialCfgModel);
    }

    /**
     * 处理大图报
     *
     * @param take
     */
    private void handleMsg_H36(FzBaowenModel take) {
        try {
            List<String> baowen = take.getBaowen();
            List<TPackLog> logs = new ArrayList<>();
            //logs 入库
            for (int i = 0; i < baowen.size(); i++) {
                TPackLog tlog = packageParse.parse_DT(baowen.get(i));
                tlog.setFlag("10");
                logs.add(tlog);
            }
            logs.get(0).setRevTime(take.getLastRevTime());
            scheduleService.handleMsg_datuBypages(logs, take.getRandomCode());
            setDeviceSn(take, logs.get(0));
            Date lastRevTime = take.getLastRevTimeMap().containsKey(HandleMsgCode.H_36) ? take.getLastRevTimeMap().get(HandleMsgCode.H_36) : take.getLastRevTime();
            tPackLogService.savePackLog(logs, lastRevTime);
        } catch (Exception e) {
            log.error("大图报解析异常:" + e.getMessage(), e);
        }
    }

    /**
     * 处理补发报
     *
     * @param take
     */
    private void handleMsg_H52(FzBaowenModel take) {
        String msg = take.getBaowen().get(0);
        TPackLog tPackLog = packageParse.parse(msg);
        //解析补发报
        List<TAiread> taireads = reissueMessageParser.parse(tPackLog, "S");
        for (int i = 0; i < taireads.size(); i++) {
            taireads.get(i).setRevTime(take.getLastRevTime());
            taireads.get(i).setRandomCode(take.getRandomCode());
            tAireadService.addTAiread(taireads.get(i));
        }
        tPackLog.setPackCount(1);//协议内没有包长
        setDeviceSn(take, tPackLog);
        Date lastRevTime = take.getLastRevTimeMap().containsKey(HandleMsgCode.H_52) ? take.getLastRevTimeMap().get(HandleMsgCode.H_52) : take.getLastRevTime();

        tPackLogService.savePackLog(tPackLog, lastRevTime);
    }

    /**
     * 处理CNN报文
     *
     * @param take
     */
    private void handleMsg_HE2(FzBaowenModel take) {
        try {
            List<String> baowen = take.getBaowen();
            List<TPackLog> logs = new ArrayList<>();
            for (int i = 0; i < baowen.size(); i++) {
                TPackLog tlog = packageParse.parse_CnnData(baowen.get(i));
                logs.add(tlog);
            }
            scheduleService.handleMsg_cnnLogsBypages(logs, take.getRandomCode());
            setDeviceSn(take, logs.get(0));
            Date lastRevTime = take.getLastRevTimeMap().containsKey(HandleMsgCode.H_E2) ? take.getLastRevTimeMap().get(HandleMsgCode.H_E2) : take.getLastRevTime();
            tPackLogService.savePackLog(logs, lastRevTime);
            logs = null;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
    }

    /**
     * 处理运行日志
     *
     * @param take
     */
    private void handleMsg_HE6(FzBaowenModel take) {
        try {
            List<String> baowen = take.getBaowen();
            List<TPackLog> logs = new ArrayList<>();
            //logs 入库
            for (int i = 0; i < baowen.size(); i++) {
                TPackLog tlog = packageParse.parse_RunLogs(baowen.get(i));
                logs.add(tlog);
            }
            scheduleService.handleMsg_runLogsBypages(logs);
            setDeviceSn(take, logs.get(0));
            Date lastRevTime = take.getLastRevTimeMap().containsKey(HandleMsgCode.H_E6) ? take.getLastRevTimeMap().get(HandleMsgCode.H_E6) : take.getLastRevTime();
            tPackLogService.savePackLog(logs, lastRevTime);
            logs = null;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
    }

    /**
     * 处理紧急域名报文
     *
     * @param take
     */
    private void handleMsg_HEA(FzBaowenModel take) {
        String msg = take.getTotalmsg().toString();
        TPackLog tPackLog = packageParse.parse_DomainContact(msg);
        setDeviceSn(take, tPackLog);
        tPackLogService.savePackLog(tPackLog, take.getLastRevTime());
    }

    /**
     * 处理版本信息
     *
     * @param model
     */
    private void handleVersionInfo(FzBaowenModel model) {
        if (StringUtils.isEmpty(model.getVersionInfo())) {
            return;
        }

        TPackLog packLog = packageParse.parse_VersionInfo(model.getVersionInfo());
        packLog.setRevTime(model.getLastRevTime());//接收时间是不准确的,滞后,使用的是定时报的时间
        TUpgradeResultsModel resultsModel = versionMessageParser.parse(packLog.getMessage());

        TUpgradePlanDetailModel detailModel = tUpgradePlanService.updateUpgradeStatus(model, resultsModel);
        if (resultsModel != null) {
            if (detailModel != null) {
                resultsModel.setPlanId(detailModel.getPlanId());
                resultsModel.setUpgradeResult(Integer.valueOf(detailModel.getUpgradeStatus()));
                packLog.setDeviceSn(resultsModel.getDeviceSn());
            } else {
                resultsModel.setUpgradeResult(-1);
            }

            resultsModel.setStationCode(model.getStationcode());
            upgradeResultsService.saveTUpgradeResults(resultsModel);
        }

        //优先使用H_ED中的时间,不然会导致报文数据界面排序错误 2024-09-19 guozhao
        Date lastRevTime = model.getLastRevTimeMap().containsKey(HandleMsgCode.H_ED) ? model.getLastRevTimeMap().get(HandleMsgCode.H_ED) : model.getLastRevTime();
        setDeviceSn(model, packLog);
        tPackLogService.savePackLog(packLog, lastRevTime);
        log.info("升级回执:[{}]:{}", model.getStationcode(), resultsModel == null ? "解析错误" : resultsModel.getVersionNum());
    }

    /**
     * 赋值SN(将FzBaowenModel中的SN给PackLog)
     *
     * @param take
     * @param packLog
     */
    private void setDeviceSn(FzBaowenModel take, TPackLog packLog) {
        //主要目的是为了降低对StationCode的依赖 2024-04-08 guozhao
        if (StringUtils.isNotEmpty(take.getSn())) {
            packLog.setDeviceSn(take.getSn());
        }
    }
}

