package com.mvc.netty;

import com.mvc.entity.TPackLog;
import com.mvc.entity.TaskReviewPush;
import com.mvc.model.TaskSpecialCfgModel;
import com.mvc.model.upgrade.TUpgradePlanModel;
import com.mvc.netty.dealconstant.DomainContactIdentifier;
import com.mvc.netty.dealconstant.HandleMsgCode;
import com.mvc.netty.dealconstant.MsgIdentifier;
import com.mvc.netty.dealconstant.PackageOperateCode;
import com.mvc.utils.CRC16Util;
import com.mvc.utils.NumberUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.*;

public class FzBaowenModel implements Serializable {
    private static Logger log = LoggerFactory.getLogger(WmNettyServerHandler_2.class);
    //private String type;//1 定时报单包  2定时报多包 3 大图 4补发报  5紧急域名联系报文 6审核任务回执 7运行日志 8CNN 9版本信息
    private HandleMsgCode type;
    private StringBuffer totalmsg = new StringBuffer();
    private String currentmsg = null;
    private List<String> baowen = new ArrayList<>();
    private List<String> peizhi = new ArrayList<>();
    private int packCount;
    private String errorflag;
    private String stationcode;
    private String sn;
    private String taskdownid;
    private String versionInfo;

    private TUpgradePlanModel upgradePlanModel;                        //对应的升级计划 2024-01-22 guozhao

    private TaskReviewPush taskReviewPush;                             //审核值下发对象 2022-08-31 guozhao
    private List<String> taskReviewPushreplay = new ArrayList<>();     //审核报文回执   2022-08-31 guozhao
    private Date lastRevTime;                                          //最后一包的接收时间 2022-09-22 guozhao
    private String randomCode;                                         //随机码(现在用通道信息做区分,可用来关联一个通道多种数据) 2022-11-09 guozhao

    /**
     * 处理图片片段式报文开始 2023-01-13 guozhao
     */
    private boolean isPartMode;                                         //密码的第一字节(0x20：边缘水表抄表器；0x21：边缘压力表读表器0x70:   服务器识别水表抄表器)
    private boolean isLastPart;                                         //密码的第二字节(默认0x20，当功能码为0x32时，作为片段标志:高4位为总片段数，低4位为当前片段)
    private int partIndex;                                              //当前的片段索引(从1开始)
    private boolean isQueryMode;                                        //是否查询模式

    /**
     * 处理图片片段式报文结束 2023-01-13 guozhao
     */

    private boolean isBeforeTask;                                        //是否是下行任务前置(MCU开机后先查任务的方式)

    private HandleMsgCode handleMsgCode;

    private String imei;

    private TaskSpecialCfgModel specialCfgModel;

    private String lastReplayMsg;//最后一次回执报文(处理重发)

    private Map<HandleMsgCode, Date> lastRevTimeMap = new HashMap<>();//报文类型对应的最后接收时间

    public HandleMsgCode getType() {
        return type;
    }

    public void setType(HandleMsgCode type) {
        this.type = type;
    }

    public StringBuffer getTotalmsg() {
        return totalmsg;
    }

    public void setTotalmsg(StringBuffer totalmsg) {
        this.totalmsg = totalmsg;
    }

    public String getCurrentmsg() {
        return currentmsg;
    }

    public void setCurrentmsg(String currentmsg) {
        this.currentmsg = currentmsg;
    }

    public List<String> getBaowen() {
        return baowen;
    }

    public void setBaowen(List<String> baowen) {
        this.baowen = baowen;
    }

    public List<String> getPeizhi() {
        return peizhi;
    }

    public void setPeizhi(List<String> peizhi) {
        this.peizhi = peizhi;
    }

    public String getErrorflag() {
        return errorflag;
    }

    public void setErrorflag(String errorflag) {
        this.errorflag = errorflag;
    }

    public String getStationcode() {
        return stationcode;
    }

    public void setStationcode(String stationcode) {
        this.stationcode = stationcode;
    }

    public String getSn() {
        return sn;
    }

    public void setSn(String sn) {
        this.sn = sn;
    }

    public int getPackCount() {
        return packCount;
    }

    public void setPackCount(int packCount) {
        this.packCount = packCount;
    }

    public String getTaskdownid() {
        return taskdownid;
    }

    public void setTaskdownid(String taskdownid) {
        this.taskdownid = taskdownid;
    }

    public String getVersionInfo() {
        return versionInfo;
    }

    public void setVersionInfo(String versionInfo) {
        this.versionInfo = versionInfo;
    }

    public TUpgradePlanModel getUpgradePlanModel() {
        return upgradePlanModel;
    }

    public void setUpgradePlanModel(TUpgradePlanModel upgradePlanModel) {
        this.upgradePlanModel = upgradePlanModel;
    }

    public TaskReviewPush getTaskReviewPush() {
        return taskReviewPush;
    }

    public void setTaskReviewPush(TaskReviewPush taskReviewPush) {
        this.taskReviewPush = taskReviewPush;
    }

    public List<String> getTaskReviewPushreplay() {
        return taskReviewPushreplay;
    }

    public void setTaskReviewPushreplay(List<String> taskReviewPushreplay) {
        this.taskReviewPushreplay = taskReviewPushreplay;
    }

    public Date getLastRevTime() {
        return lastRevTime;
    }

    public void setLastRevTime(Date lastRevTime) {
        this.lastRevTime = lastRevTime;
    }

    public String getRandomCode() {
        return randomCode;
    }

    public void setRandomCode(String randomCode) {
        this.randomCode = randomCode;
    }

    public boolean isPartMode() {
        return isPartMode;
    }

    public void setPartMode(boolean partMode) {
        isPartMode = partMode;
    }

    public boolean isLastPart() {
        return isLastPart;
    }

    public void setLastPart(boolean lastPart) {
        isLastPart = lastPart;
    }

    public HandleMsgCode getHandleMsgCode() {
        return handleMsgCode;
    }

    public void setHandleMsgCode(HandleMsgCode handleMsgCode) {
        this.handleMsgCode = handleMsgCode;
    }


    public boolean isBeforeTask() {
        return isBeforeTask;
    }

    public void setBeforeTask(boolean beforeTask) {
        isBeforeTask = beforeTask;
    }

    public boolean isQueryMode() {
        return isQueryMode;
    }

    public void setQueryMode(boolean queryMode) {
        isQueryMode = queryMode;
    }

    public String getImei() {
        return imei;
    }

    public void setImei(String imei) {
        this.imei = imei;
    }

    public TaskSpecialCfgModel getSpecialCfgModel() {
        return specialCfgModel;
    }

    public void setSpecialCfgModel(TaskSpecialCfgModel specialCfgModel) {
        this.specialCfgModel = specialCfgModel;
    }

    public String getLastReplayMsg() {
        return lastReplayMsg;
    }

    public void setLastReplayMsg(String lastReplayMsg) {
        this.lastReplayMsg = lastReplayMsg;
    }

    public Map<HandleMsgCode, Date> getLastRevTimeMap() {
        return lastRevTimeMap;
    }

    public void addLastRevTimeMap(HandleMsgCode handleMsgCode, Date lastRevTime) {
        if (lastRevTimeMap == null) {
            lastRevTimeMap = new HashMap<>();
        }
        lastRevTimeMap.put(handleMsgCode, lastRevTime);
    }

    //设备SN的标识符
    private static final String IDENTIFIER_SN = DomainContactIdentifier.FF08.getKey().toLowerCase();

    public void parse() {
        //到报文起始符14字节 //是否有头信息
        if (currentmsg.length() < 34 || !currentmsg.substring(0, 4).equals(PackageOperateCode.SOH.getKey().toLowerCase())) {
            return;
        }

        //判断类型，长度
        String direandlength = currentmsg.substring(22, 26);
        String idenStr = NumberUtil.hexStringToBinaryString(direandlength);
        //int identifier = NumberUtil.binaryToDecimal(idenStr.substring(0, 4));
        int bodyLength = NumberUtil.binaryToDecimal(idenStr.substring(4));
        if (currentmsg.length() < bodyLength * 2 + 34) {
            return;
        }
        boolean crcflag = CRC16Util.checkBanwenCrc(currentmsg.substring(0, bodyLength * 2 + 34));
        if (!crcflag) {
            errorflag = "1";
            return;
        }

        //本段报文,在前面出现过
        if (totalmsg.indexOf(currentmsg) != totalmsg.length() - currentmsg.length()) {
            totalmsg.delete(totalmsg.length() - currentmsg.length(), totalmsg.length());
            currentmsg = "";
            log.info("报文重复:ID{}", stationcode);
            return;
        }

        handleMsgCode = HandleMsgCode.get(currentmsg.substring(20, 22));
        if (handleMsgCode == HandleMsgCode.H_32) {//定时报，或者多包
            if (currentmsg.substring(26, 28).equals("16")) {//多包定时报
                isPartMode = currentmsg.startsWith("70", 16);                   //是否片段模式    2023-01-13 guozhao
                isLastPart = currentmsg.substring(18, 19).equals(currentmsg.substring(19, 20)); //是否最后一个part 2023-01-13 guozhao

                type = (type == null) ? handleMsgCode : type;
                baowen.add(currentmsg.substring(0, bodyLength * 2 + 34));
                if (baowen.get(0).indexOf(IDENTIFIER_SN) > 0) {
                    int index = baowen.get(0).indexOf(IDENTIFIER_SN);
                    sn = (sn == null) ? baowen.get(0).substring(index + 6, index + 17) : sn;
                }
                //包总数
                String binarystr = NumberUtil.hexStringToBinaryString(currentmsg.substring(28, 34));
                int baonum = NumberUtil.binaryToDecimal(binarystr.substring(0, 12));
                if (isPartMode) {//片段式的,总包数会变化
                    int index = Integer.valueOf(currentmsg.substring(19, 20));
                    if (index > partIndex) {
                        packCount += baonum;
                        partIndex = index;
                        System.out.println("第" + partIndex + "片段开始");
                    }
                    ////packCount=baonum==packCount?packCount:packCount+baonum;
                } else {
                    packCount = (packCount == 0) ? baonum : packCount;
                }
                partIndex = Integer.valueOf(currentmsg.substring(19, 20));
                stationcode = (stationcode == null) ? currentmsg.substring(6, 16) : stationcode;

                currentmsg = currentmsg.substring(bodyLength * 2 + 34);
                parse();
            } else {//单包定时报
                type = (type == null) ? HandleMsgCode.VIRT_H_31 : type;
                baowen.add(currentmsg.substring(0, bodyLength * 2 + 34));
                if (baowen.get(0).indexOf(IDENTIFIER_SN) > 0) {
                    int index = baowen.get(0).indexOf(IDENTIFIER_SN);
                    sn = (sn == null) ? baowen.get(0).substring(index + 6, index + 17) : sn;//sn 取11位
                }
                stationcode = (stationcode == null) ? currentmsg.substring(6, 16) : stationcode;
                currentmsg = currentmsg.substring(bodyLength * 2 + 34);
                return;
            }
            addLastRevTimeMap(handleMsgCode, new Date());
        } else if (handleMsgCode == HandleMsgCode.H_52) {//补发报
            type = (type == null) ? handleMsgCode : type;
            baowen.add(currentmsg.substring(0, bodyLength * 2 + 34));
            stationcode = (stationcode == null) ? currentmsg.substring(6, 16) : stationcode;
            currentmsg = currentmsg.substring(bodyLength * 2 + 34);
            addLastRevTimeMap(handleMsgCode, new Date());
            return;
        } else if (handleMsgCode == HandleMsgCode.H_36) {//大图
            type = (type == null) ? handleMsgCode : type;
            baowen.add(currentmsg.substring(0, bodyLength * 2 + 34));
            //包总数
            String binarystr = NumberUtil.hexStringToBinaryString(currentmsg.substring(28, 34));
            int baonum = NumberUtil.binaryToDecimal(binarystr.substring(0, 12));
            packCount = (packCount == 0) ? baonum : packCount;
            stationcode = (stationcode == null) ? currentmsg.substring(6, 16) : stationcode;    //g
            currentmsg = currentmsg.substring(bodyLength * 2 + 34);
            parse();
            addLastRevTimeMap(handleMsgCode, new Date());
        } else if (handleMsgCode == HandleMsgCode.H_E1) {//设备配置
            peizhi.add(currentmsg.substring(0, bodyLength * 2 + 34));
            currentmsg = currentmsg.substring(bodyLength * 2 + 34);

            addLastRevTimeMap(handleMsgCode, new Date());
            return;
        } else if (handleMsgCode == HandleMsgCode.H_EA) {//紧急域名联系报文
            type = (type == null) ? handleMsgCode : type;
            stationcode = (stationcode == null) ? currentmsg.substring(6, 16) : stationcode;
            if (currentmsg.indexOf(IDENTIFIER_SN) > 0) {
                int index = currentmsg.indexOf(IDENTIFIER_SN);
                sn = (sn == null) ? currentmsg.substring(index + 6, index + 17) : sn;//sn 取11位
            }
            currentmsg = currentmsg.substring(bodyLength * 2 + 34);
        } else if (handleMsgCode == HandleMsgCode.H_E5) {//设备端应答服务器下发0xE4审核值任务
            type = (type == null) ? handleMsgCode : type;
            taskReviewPushreplay.add(currentmsg.substring(0, bodyLength * 2 + 34));
            currentmsg = currentmsg.substring(bodyLength * 2 + 34);
            addLastRevTimeMap(handleMsgCode, new Date());
            return;
        } else if (handleMsgCode == HandleMsgCode.H_E6) {//运行日志
            type = (type == null) ? handleMsgCode : type;
            baowen.add(currentmsg.substring(0, bodyLength * 2 + 34));
            //包总数
            String binarystr = NumberUtil.hexStringToBinaryString(currentmsg.substring(28, 34));
            int baonum = NumberUtil.binaryToDecimal(binarystr.substring(0, 12));
            packCount = (packCount == 0) ? baonum : packCount;
            stationcode = (stationcode == null) ? currentmsg.substring(6, 16) : stationcode;
            currentmsg = currentmsg.substring(bodyLength * 2 + 34);
            addLastRevTimeMap(handleMsgCode, new Date());
            parse();
        } else if (handleMsgCode == HandleMsgCode.H_E2) {//cnn网络输出数据
            type = (type == null) ? handleMsgCode : type;
            baowen.add(currentmsg.substring(0, bodyLength * 2 + 34));
            //包总数
            String binarystr = NumberUtil.hexStringToBinaryString(currentmsg.substring(28, 34));
            int baonum = NumberUtil.binaryToDecimal(binarystr.substring(0, 12));
            packCount = (packCount == 0) ? baonum : packCount;
            stationcode = (stationcode == null) ? currentmsg.substring(6, 16) : stationcode;
            currentmsg = currentmsg.substring(bodyLength * 2 + 34);
            addLastRevTimeMap(handleMsgCode, new Date());
            parse();
        } else if (handleMsgCode == HandleMsgCode.H_F0) {//遥测站向中心站查询服务器IP地址
            stationcode = (stationcode == null) ? currentmsg.substring(6, 16) : stationcode;
            setDeviceSn();
            isQueryMode = true;
            return;
        } else if (handleMsgCode == HandleMsgCode.H_F2) {//遥测站向中心站查询其它任务
            stationcode = (stationcode == null) ? currentmsg.substring(6, 16) : stationcode;
            setDeviceSn();
            isBeforeTask = true;
            return;
        } else if (handleMsgCode == HandleMsgCode.H_ED) {//遥测站向中心站查询其它任务
            stationcode = (stationcode == null) ? currentmsg.substring(6, 16) : stationcode;
            versionInfo = currentmsg;
            setDeviceSn();
            //防止后收到的ED报文

            int index = totalmsg.indexOf(currentmsg);
            if (index > -1) {
                totalmsg = totalmsg.replace(index, index + currentmsg.length(), "");
            }
            currentmsg = currentmsg.replaceAll(currentmsg, "");
            addLastRevTimeMap(handleMsgCode, new Date());
            return;
        } else if (handleMsgCode == HandleMsgCode.H_E3) {//根据IMEI配置设备SN的回执报文 2024-04-23 guozhao
            if (specialCfgModel != null) {
                specialCfgModel.setReplyMessage(currentmsg);
            }
            currentmsg = currentmsg.substring(bodyLength * 2 + 34);
            addLastRevTimeMap(handleMsgCode, new Date());
            return;
        } else {
            errorflag = "1";
        }
    }

    /**
     * 提取设备SN
     */
    private void setDeviceSn() {
        if (currentmsg.indexOf(IDENTIFIER_SN) > 0) {
            int index = currentmsg.indexOf(IDENTIFIER_SN);
            sn = (sn == null) ? currentmsg.substring(index + 6, index + 17) : sn;//sn 取11位
        }
    }

    /**
     * 解析IMEI
     */
    public String parseImei(PackageParse packageParse) {
        if (baowen == null || baowen.size() == 0) {
            return null;
        }
        TPackLog tlog = packageParse.parse_duobao(baowen.get(0));
        String temp = tlog.getMessage();
        // 解析报文
        List<String> keys = MsgIdentifier.keys();
        while (!io.netty.util.internal.StringUtil.isNullOrEmpty(temp)) {
            boolean blnFind = false;
            for (String key : keys) {
                if (!temp.toUpperCase().startsWith(key)) {
                    continue;
                }

                MsgIdentifier identifier = MsgIdentifier.getElement(key);
                if (identifier == null) {
                    continue;
                }

                try {
                    if (identifier == MsgIdentifier.FF06) {     // 图片内容
                        //常规情况下,数据内容一定在图片前面,不需要解析图片
                        temp = "";
                        blnFind = false;
                        break;
                    } else if (identifier == MsgIdentifier.FF22) {//调试信息
                        temp = identifier.parseDebugInfo(temp);
                    } else if (identifier == MsgIdentifier.FF35) {//AI图片占用字节描述2 2022-11-08 guozhao
                        temp = identifier.parseImageDescribe(temp);
                    } else {
                        temp = identifier.parse(temp);
                        if (identifier == MsgIdentifier.FF38) {
                            String value = identifier.getValue().length() > 15 ? identifier.getValue().substring(1) : identifier.getValue();
                            setImei(value);
                            return value;
                        }
                    }
                    blnFind = true;
                } catch (Exception e) {
                    e.printStackTrace();
                    blnFind = false;
                }
                break;
            }
            if (blnFind == false) {
                break;
            }
        }
        return null;
    }
}
