package org.ts.ddcs.DataTemplate;


import com.alibaba.fastjson.JSONObject;
import org.ts.ddcs.DataItemTemplate.DataItemTemplateInterface;
import org.ts.ddcs.Log.LogHelper;
import org.ts.ddcs.Tool.BytesHelp;
import org.ts.ddcs.Worker.DataProcess;
import org.ts.ddcs.utils.GBConstants;

import java.util.*;

/**
 * created by swp on 2017/8/23
 */
@SuppressWarnings("all")
public abstract class DataTemplate implements DataTemplateInterface {
    protected String templateName;
    protected String fetureKey;
    protected boolean macth = false;
    protected byte[] startFlag;
    protected byte[] centerStation;
    protected byte[] rtuCode;
    protected byte[] rtuPassword;
    protected byte[] funcCode;
    protected int dataLen;
    protected byte[] dataArea;
    protected byte[] dataAreaStart;
    protected byte[] dataAreaEnd;
    protected byte[] crc;
    protected String supplementInfo;
    protected boolean needCheckOutlierData = false;

    protected HashMap<String, DataItemTemplateInterface> dataItem;

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

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

    @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.fetureKey);
        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 GetFeture() {
        return this.fetureKey;
    }

    @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, 2));
        if (!sf.equals("7E7E")) {
            return macth;
        }
        if (DataProcess.config().getCodeExt().equals("1")) {
            byte[] fc = BytesHelp.subBytes(data, 13, 1);
            if (this.fetureKey.equals(BytesHelp.byte2HexStr(fc))) {
                int count = 0;
                startFlag = BytesHelp.subBytes(data, count, 2);
                count += 2;
                centerStation = BytesHelp.subBytes(data, count, 1);
                count += 1;

                rtuCode = BytesHelp.subBytes(data, count, 8);
                count += 8;


                rtuPassword = BytesHelp.subBytes(data, count, 2);
                count += 2;
                funcCode = BytesHelp.subBytes(data, count, 1);
                count += 1;
                //报文上下行标识及长度  高四位用作上下行标识（0000 表示上行，1000，表示下行）；
                //其余12位表示报文正文长度，表示报文起始符之后，报文结束符之前的报文字节数，允许长度为0001-4095
                byte[] dataAreaLen2014 = BytesHelp.subBytes(data, count, 2);
                count += 2;
                dataLen = BytesHelp.bytes2Int(dataAreaLen2014, 0, dataAreaLen2014.length);// 报文长度(int)

                dataAreaStart = BytesHelp.subBytes(data, count, 1);
                count += 1;

                if (dataLen > 0) {
                    dataArea = BytesHelp.subBytes(data, count, dataLen);
                }
                count += dataLen;
                dataAreaEnd = BytesHelp.subBytes(data, count, 1);
                count += 1;
                crc = BytesHelp.subBytes(data, count, 2);
                count += 2;
                if (data.length == count) {
                    this.macth = true;
                } else {
                    LogHelper.info("*************************   macth error *********************");
                }
            }
        } else {
            byte[] fc = BytesHelp.subBytes(data, 10, 1);
            if (this.fetureKey.equals(BytesHelp.byte2HexStr(fc))) {
                int count = 0;
                startFlag = BytesHelp.subBytes(data, count, 2);
                count += 2;
                centerStation = BytesHelp.subBytes(data, count, 1);
                count += 1;

                rtuCode = BytesHelp.subBytes(data, count, 5);
                count += 5;


                rtuPassword = BytesHelp.subBytes(data, count, 2);
                count += 2;
                funcCode = BytesHelp.subBytes(data, count, 1);
                count += 1;
                //报文上下行标识及长度  高四位用作上下行标识（0000 表示上行，1000，表示下行）；
                //其余12位表示报文正文长度，表示报文起始符之后，报文结束符之前的报文字节数，允许长度为0001-4095
                byte[] dataAreaLen2014 = BytesHelp.subBytes(data, count, 2);
                count += 2;
                dataLen = BytesHelp.bytes2Int(dataAreaLen2014, 0, dataAreaLen2014.length);// 报文长度(int)

                dataAreaStart = BytesHelp.subBytes(data, count, 1);
                count += 1;

                if (dataLen > 0) {
                    dataArea = BytesHelp.subBytes(data, count, dataLen);
                }
                count += dataLen;
                dataAreaEnd = BytesHelp.subBytes(data, count, 1);
                count += 1;
                crc = BytesHelp.subBytes(data, count, 2);
                count += 2;
                if (data.length == count) {
                    this.macth = true;
                } else {
                    LogHelper.info("*************************   macth error *********************");
                }
            }
        }

        return this.macth;
    }

    @Override
    public LinkedList<DataItemTemplateInterface> MacthDataItem(String tableName) {
        LinkedList<DataItemTemplateInterface> macthItem = 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)) {
                    macthItem.addLast(item);
                }
            }
        }
        return macthItem;
    }

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

    @Override
    public void Stream() {
    }

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

    @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;
    }
}
