package  org.ts.ddcs.datatemplate.swDataTemplate;


import org.ts.ddcs.common.constant.GBConstants;
import org.ts.ddcs.dataStream.DataStreamAdapter;
import org.ts.ddcs.dataStream.DataStreamInterface;
import org.ts.ddcs.dataprocesser.DataProcesserInterface;
import org.ts.ddcs.datatemplate.DataTemplate;
import org.ts.ddcs.datatemplate.DataTemplateInterface;
import org.ts.ddcs.datatemplate.TestState;
import org.ts.ddcs.datatemplate.tool.DataItemTemplateHelp;
import org.ts.ddcs.filter.DataFilter;
import org.ts.ddcs.log.LogHelper;
import org.ts.ddcs.util.BusinessConstant;
import org.ts.ddcs.util.BytesUtil;



/**
 * 2014 规约报文数据模板
 * @author dylan
 */
public class DataTemplate2014 extends DataTemplate implements DataTemplateInterface {

    /**
     * 包数据
     */
    protected byte[] packet = null;
    /**
     * 命令(HEX_2)
     */
    protected byte command = 0;
    /**
     * 报文头7E7E
     */
    protected byte[] packetHeader;
    /**
     * 中心站地址
     */
    protected byte[] centerStation;
    /**
     * RTU地址
     */
    protected byte[] rtuCodeByte;
    /**
     * RTU密码
     */
    protected byte[] rtuPw;
    /**
     * 功能码
     */
    protected byte[] funcCode;
    /**
     * 报文上下行标识及长度
     */
    protected byte[] dataAreaLen;
    /**
     * 报文起始符
     */
    protected byte[] dataAreaStartFlag;
    /**
     * 报文正文
     */
    protected byte[] dataArea;
    /**
     * 报文起始符
     */
    protected byte[] dataAreaEndFlag;
    /**
     * 校验码
     */
    protected byte[] packetCrc16;


    @Override
    public void stream(DataStreamInterface stream) {
        LogHelper.info("SwDataTemplate2014 stream");
        if (stream.dataSize() == 0) {
            return;
        }
        if (stream.getByte(0) != 0x7E) {
            this.state = TestState.UNKNOWN;
            return;
        }
        if (stream.dataSize() < 2) {
            return;
        }
        if (stream.getByte(0) != 0x7E || stream.getByte(1) != 0x7E) {
            this.state = TestState.UNKNOWN;
            return;
        }
        if (stream.dataSize() < this.featureWeight) {
            return;
        }
        byte[] feture = stream.getBytes(this.featureWeight);
        if (!this.checkFeature(feture, 0, feture.length)) {
            this.state = TestState.UNKNOWN;
            return;
        }


        int count = 0;
        if (stream.dataSize() < 13) {
            return;
        }

        byte[] dataAreaLen = new byte[2];
        dataAreaLen[0] = stream.getByte(11);
        dataAreaLen[1] = stream.getByte(12);
        int len =   DataItemTemplateHelp.getContentLen(dataAreaLen);
        if (len > BusinessConstant.DATAGRAM_BODY_MAX_LEN){
            this.state = TestState.UNKNOWN;
            return;
        }
       // int len = BytesUtil.byteslowbitToInt(dataAreaLen, 0);// 报文长度(int)
        this.length = 11 + len + 6;
        if (stream.dataSize() < (11 + len + 6)) {
            return;
        }
        this.packet = stream.getBytes(this.length);


        this.packetHeader = new byte[2];
        System.arraycopy(this.packet, count, this.packetHeader, 0, 2);
        count += 2;

        //中心站地址
        this.centerStation = new byte[1];
        System.arraycopy(this.packet, count, this.centerStation, 0, 1);
        count += 1;
        //RTU地址
        this.rtuCodeByte = new byte[5];
        System.arraycopy(this.packet, count, this.rtuCodeByte, 0, 5);
        count += 5;

        //RTU密码
        this.rtuPw = new byte[2];
        System.arraycopy(this.packet, count, this.rtuPw, 0, 2);
        count += 2;

        //功能码
        this.funcCode = new byte[1];
        System.arraycopy(this.packet, count, this.funcCode, 0, 1);
        count += 1;

        this.command = this.funcCode[0];
        //报文上下行标识及长度  高四位用作上下行标识（0000 表示上行，1000，表示下行）；
        //其余12位表示报文正文长度，表示报文起始符之后，报文结束符之前的报文字节数，允许长度为0001-4095
        this.dataAreaLen =dataAreaLen;
        System.arraycopy(this.packet, count, this.dataAreaLen, 0, 2);
        count += 2;
       // len = BytesUtil.bytes2Int(this.dataAreaLen, 0, this.dataAreaLen.length);// 报文长度(int)

        //报文起始符
        this.dataAreaStartFlag = new byte[1];
        System.arraycopy(this.packet, count, this.dataAreaStartFlag, 0, 1);
        count += 1;

        //报文正文
        this.dataArea = new byte[len];
        System.arraycopy(this.packet, count, this.dataArea, 0, len);
        count += len;

        //报文起始符
        this.dataAreaEndFlag = new byte[1];
        System.arraycopy(this.packet, count, this.dataAreaEndFlag, 0, 1);
        count += 1;

        //校验码
        this.packetCrc16 = new byte[2];
        System.arraycopy(this.packet, count, this.packetCrc16, 0, 2);
        count += 2;

        this.state = TestState.MATHCE;
    }

    @Override
    public boolean checkFeature(byte[] check, int pos, int length) {
        boolean match = true;
        if (null == this.featureIndex || null == this.featureKey) {
            return match;
        }
        if (length < this.featureKey.length) {
            return false;
        }
        for (int i = 0; i < this.featureIndex.length; i++) {
            if (this.featureKey[this.featureIndex[i]] != check[this.featureIndex[i]]) {
                match = false;
                break;
            }
        }
        return match;
    }

    @Override
    public void ready() {
        this.state = TestState.LOOK;
    }

    @Override
    public int length() {
        return this.length;
    }

    @Override
    public TestState state() {
        return this.state;
    }

    @Override
    public int featureWeight() {
        return this.featureWeight;
    }

    @Override
    public void setFeatureWeight(int weight) {
        this.featureWeight = weight;
    }

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

    @Override
    public void setName(String name) {
        this.templateName = name;
    }

    @Override
    public void bridgeDataProcessor(DataProcesserInterface processer, DataStreamAdapter dataStreamAdapter) {
        processer.packetReadly(this.packet, 0, this.packet.length, dataStreamAdapter, this);
    }

    @Override
    public boolean bridgeDataFilter(DataFilter filter, DataStreamAdapter dataStreamAdapter) {
        return filter.filter(this.packet, 0, this.packet.length, dataStreamAdapter, this);
    }

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

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

    @Override
    public byte[] datagramContext() {
        return this.packet;
    }

    @Override
    public String agreement() {
        return "";
    }

    @Override
    public boolean hasNext() {
        return false;
    }

    @Override
    public int packageTotal() {
        return 0;
    }

    @Override
    public int packageIndex() {
        return 0;
    }

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