package org.ts.ddcs.DataTemplate.jtTemplate;


import com.alibaba.fastjson.JSONObject;
import org.ts.ddcs.DataItemTemplate.DataItemTemplateInterface;
import org.ts.ddcs.DataItemTemplate.tool.DataItemTemplateHelp;
import org.ts.ddcs.DataItemTemplate.tool.ValueLen;
import org.ts.ddcs.DataTemplate.DataTemplateInterface;
import org.ts.ddcs.DataTemplate.TemplateSet;
import org.ts.ddcs.log.LogHelper;
import org.ts.ddcs.Tool.BytesHelp;
import org.ts.ddcs.utils.GBConstants;

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

/**
 * created by swp on 2017/8/23
 *
 * @author dylan
 */
public abstract class JtDataTemplate implements DataTemplateInterface, Serializable {

    /**
     * 数据包
     */
    protected byte[] packet;

    /**
     * 功能码
     */
    protected byte[] funcCode;


    /**
     * 报文正文
     */
    protected byte[] dataArea;

    /**
     * 版本号
     */
    protected byte[] ver;

    /**
     * 设备号
     */
    protected byte[] deviceId;

    /**
     * 流水号
     */
    protected byte[] datagramIndex;

    /**
     * 分包
     */
    protected boolean hasNext;

    /**
     * 包总数
     */
    protected int packageTotal;

    /**
     * 包序号
     */
    protected int packageIndex;

    /**
     * 加密 1
     */
    protected String rsa;

    /**
     * 检验码
     */
    protected byte[] crc;


    protected String templateName;
    protected String featureKey;
    protected boolean match = false;

    protected byte[] centerStation;
    protected byte[] rtuCode;
    protected byte[] rtuPassword;

    protected int dataLen;

    protected byte[] dataAreaEnd;
    protected byte[] valueContent;

    protected String supplementInfo;
    protected boolean needCheckOutlierData = false;
    protected TemplateSet templateSet;


    protected HashMap<String, DataItemTemplateInterface> dataItem;

    @Override
    public void Init(TemplateSet template) {
        this.templateSet = template;
        this.featureKey = template.feature;
        this.templateName = template.dataTemplate;
    }

    @Override
    public String toString() {
        return templateName + " []";
    }

//    @Override
//    public TemplateSet GetTemplateSet() {
//        return this.templateSet;
//    }

//    @Override
//    public Map<String, byte[]> GetValues() {
//        if (null != valueContent && valueContent.length > 0) {
//            Map<String, byte[]> values = new HashMap<>();
//            int count = 0;
//            while (true) {
//                if (count >= valueContent.length) {
//                    break;
//                }
//                String flag = BytesHelp.byte2HexStr(valueContent, count, 1);
//                String flag2 = BytesHelp.byte2HexStr(valueContent, count + 1, 1);
//                if ("FF".equals(flag)) {
//                    byte[] len = BytesHelp.subBytes(valueContent, count + 2, 1);
//                    ValueLen valueLen = DataItemTemplateHelp.getValueLen(len[0]);
//                    byte[] buff = BytesHelp.subBytes(valueContent, count, 3 + valueLen.getByteLen());
//                    count += 3 + valueLen.getByteLen();
//                    values.put(flag + flag2, buff);
//                } else if (flag.substring(0, 1).equals("F") && flag.equals(flag2)) {
//                    byte[] len = BytesHelp.subBytes(valueContent, count + 2, 1);
//                    ValueLen valueLen = DataItemTemplateHelp.getValueLen(len[0]);
//                    byte[] buff = BytesHelp.subBytes(valueContent, count, 3 + valueLen.getByteLen());
//                    count += 3 + valueLen.getByteLen();
//                    values.put(flag + flag2, buff);
//                } else {
//                    byte[] len = BytesHelp.subBytes(valueContent, count + 1, 1);
//                    ValueLen valueLen = DataItemTemplateHelp.getValueLen(len[0]);
//                    byte[] buff = BytesHelp.subBytes(valueContent, count, 2 + valueLen.getByteLen());
//                    count += 2 + valueLen.getByteLen();
//                    values.put(flag, buff);
//                }
//            }
//            return values;
//        }
//        return null;
//    }

//    @Override
//    public byte[] Packet() {
//        return packet;
//    }

    @Override
    public String GetFeture() {
        return this.featureKey;
    }

    @Override
    public String GetAgreement() {
        return GBConstants.AGREEMENT_KIND_JT;
    }

    @Override
    public String GetDatagram() {
        return null;
    }

    @Override
    public boolean ClearCommand() {
        return true;
    }

    @Override
    public void SupplementInfo(String supplementInfo) {
        this.supplementInfo = supplementInfo;
    }

    @Override
    public String SupplementInfo() {
        return supplementInfo;
    }

    @Override
    public boolean NeedCheckOutlierData() {
        return this.needCheckOutlierData;
    }

    @Override
    public List<DataItemTemplateInterface> OutlierData() {
        if (null != this.dataItem) {
            List<DataItemTemplateInterface> outlierDataList = new LinkedList<>();
            Set<String> keys = this.dataItem.keySet();
            for (String key : keys) {
                DataItemTemplateInterface itemTemplateInterface = (DataItemTemplateInterface) this.dataItem.get(key);
                if (itemTemplateInterface.OutlierData()) {
                    outlierDataList.add(itemTemplateInterface);
                }
            }
            return outlierDataList;
        }
        return null;
    }

    @Override
    public String getDataInfo() {
        JSONObject data = new JSONObject();
        data.put("func", this.featureKey);
        List<JSONObject> items = new LinkedList<>();
        data.put("data", items);
        return data.toJSONString();
    }

    @Override
    public byte[] GetEndFlag() {
        return this.dataAreaEnd;
    }

    @Override
    public byte[] GetContent() {
        return this.dataArea;
    }


    @Override
    public String GetViewName() {
        return "水文报文";
    }

    @Override
    public String GetName() {
        return this.templateName;
    }

    @Override
    public boolean Macth(byte[] data) {
        String sf = BytesHelp.byte2HexStr(BytesHelp.subBytes(data, 0, 1));
        if (!sf.equals("7E")) {
            return match;
        }
        byte[] fc = BytesHelp.subBytes(data, 1, 2);
        if (this.featureKey.equals(BytesHelp.byte2HexStr(fc))) {

            int count = 0;
            //start flag
            count += 1;
            this.funcCode = new byte[2];
            System.arraycopy(data, count, this.funcCode, 0, 2);
            count += 2;
            byte[] parameter = new byte[2];
            System.arraycopy(data, count, parameter, 0, 2);
            count += 2;
            String bin = BytesHelp.BytesToBinStr(parameter);
            String nextFlag = bin.substring(2, 3);
            if (nextFlag.equals("1")) {
                this.hasNext = true;
            } else {
                this.hasNext = false;
            }
            String rsa = bin.substring(3, 6);
            if (rsa.equals("000")) {
                this.rsa = "0";
            } else {
                this.rsa = "1";
            }
            String bodyLenStr = "000000" + bin.substring(6, 16);
            this.dataLen = Integer.parseUnsignedInt(bodyLenStr, 2);


            this.ver = new byte[1];
            System.arraycopy(data, count, this.ver, 0, 1);
            count += 1;

            this.deviceId = new byte[10];
            System.arraycopy(data, count, this.deviceId, 0, 10);
            count += 10;

            //流水号
            this.datagramIndex = new byte[2];
            System.arraycopy(data, count, this.datagramIndex, 0, 2);
            count += 2;

            //分包信息
            if (this.hasNext) {
                byte[] packageTotalBuff = new byte[2];
                System.arraycopy(data, count, packageTotalBuff, 0, 2);
                this.packageTotal = BytesHelp.bytes2Int(packageTotalBuff, 0, 2);
                count += 2;
                byte[] packageIndexBuff = new byte[2];
                System.arraycopy(data, count, packageIndexBuff, 0, 2);
                this.packageIndex = BytesHelp.bytes2Int(packageIndexBuff, 0, 2);
                count += 2;
            }

            if (this.dataLen > 0) {
                this.dataArea = new byte[this.dataLen];
                System.arraycopy(data, count, this.dataArea, 0, this.dataLen);
                count += this.dataLen;

            }

            this.crc = new byte[1];
            System.arraycopy(data, count, this.crc, 0, 1);
            count += 1;
            //end flag
            count += 1;

            if (data.length == count) {
                this.packet = new byte[data.length];
                System.arraycopy(data, 0, this.packet, 0, count);
                this.match = true;
            } else {
                LogHelper.info("*************************   match error *********************");
            }
        }

        return this.match;
    }

    @Override
    public LinkedList<DataItemTemplateInterface> MacthDataItem() {
        LinkedList<DataItemTemplateInterface> matchItem = new LinkedList<>();
        if (dataItem != null && dataItem.size() > 0) {
            Set<String> keys = dataItem.keySet();
            for (String key : keys) {
                DataItemTemplateInterface item = dataItem.get(key);
                matchItem.addLast(item);
            }
        }
        return matchItem;
    }

    @Override
    public LinkedList<DataItemTemplateInterface> MacthDataItem(String tableName) {
        LinkedList<DataItemTemplateInterface> matchItem = new LinkedList<>();
        if (dataItem != null && dataItem.size() > 0) {
            Set<String> keys = dataItem.keySet();
            for (String key : keys) {
                DataItemTemplateInterface item = dataItem.get(key);
                if (item.GetTableName().equals(tableName)) {
                    matchItem.addLast(item);
                }
            }
        }
        return matchItem;
    }

    @Override
    public LinkedList<DataItemTemplateInterface> matchDataItem(String tableName, String column) {
        LinkedList<DataItemTemplateInterface> matchItem = new LinkedList<>();
        if (dataItem != null && dataItem.size() > 0) {
            Map<String, String> columnMap = new HashMap<>();
            if (null != column) {
                String[] columnArr = column.split(",");
                for (String c : columnArr) {
                    columnMap.put(c, c);
                }
            }

            Set<String> keys = dataItem.keySet();
            for (String key : keys) {
                DataItemTemplateInterface item = dataItem.get(key);
                if (null != tableName) {
                    if (item.GetTableName().equals(tableName)) {
                        if (null != column) {
                            if (columnMap.containsKey(item.GetColumnName())) {
                                matchItem.addLast(item);
                            }
                        } else {
                            matchItem.addLast(item);
                        }

                    }
                } else {
                    if (null != column) {
                        if (columnMap.containsKey(item.GetColumnName())) {
                            matchItem.addLast(item);
                        }
                    } else {
                        matchItem.addLast(item);
                    }
                }
            }
        }
        return matchItem;
    }

    @Override
    public LinkedList<DataItemTemplateInterface> matchDataItemByFeature(String feature) {
        LinkedList<DataItemTemplateInterface> matchItem = new LinkedList<>();
        if (dataItem != null && dataItem.size() > 0) {
            Set<String> keys = dataItem.keySet();
            for (String key : keys) {
                DataItemTemplateInterface item = dataItem.get(key);
                if (item.GetFeture().equals(feature)) {
                    matchItem.addLast(item);
                }
            }
        }
        return matchItem;
    }

    @Override
    public boolean Macth() {
        return this.match;
    }

    @Override
    public void Stream() {
    }

    @Override
    public byte[] RtuCode() {
        return this.deviceId;
    }

    @Override
    public byte[] CenterStation() {
        return this.centerStation;
    }

    @Override
    public byte[] RtuPassword() {
        return this.rtuPassword;
    }

    @Override
    public byte[] FuncCode() {
        return this.funcCode;
    }

    @Override
    public byte[] SerialNo() {
        return new byte[0];
    }

    @Override
    public byte[] SendPacketTime() {
        return new byte[0];
    }

    @Override
    public byte[] ReceiveTime() {
        return new byte[0];
    }

    @Override
    public byte[] SiteKind() {
        return new byte[0];
    }

    @Override
    public byte[] CollectTime() {
        return new byte[0];
    }


    @Override
    public HashMap<String, DataItemTemplateInterface> DataItem() {
        return this.dataItem;
    }

    @Override
    public List<Map<String, String>> toTextInfo() {
        List<Map<String, String>> textInfo = new LinkedList<>();
        if (dataItem != null && dataItem.size() > 0) {
            Set<String> keys = dataItem.keySet();
            for (String key : keys) {
                DataItemTemplateInterface item = dataItem.get(key);
                Map<String, String> text = new HashMap<>();
                text.put("name", item.GetDesc());
                text.put("value", item.toString());
                textInfo.add(text);
            }
        }
        return textInfo;
    }

}
