/**
 * Copyright 2019 DH
 * All right reserved.
 * 项目名称: 大恒泰山系统
 * 创建日期:2023/9/4
 */
package org.ts.ddcs.dataStream.processor.szy;

import lombok.extern.slf4j.Slf4j;
import org.ts.ddcs.common.util.BytesHelp;
import org.ts.ddcs.dataStream.DataStreamAdapter;
import org.ts.ddcs.dataStream.DataStreamCache;
import org.ts.ddcs.dataStream.DataStreamLineManager;
import org.ts.ddcs.dataStream.DataStreamProcessor;
import org.ts.ddcs.datatemplate.TestState;
import org.ts.ddcs.metadata.DataStreamCacheMetadata;

import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;

/***
 * Date:2023/9/4
 * Title:水资源规约数据处理器模块
 * Description：水资源报文检测处理器，主要负责检测出一个完整正确的报文
 * @author dylan
 * @version 1.0
 * Remark：认为有必要的其他信息
 */
@Slf4j
public class DataStreamSzyMatchDatagramProcessor extends DataStreamProcessor {
    private DataStreamCache dataStreamCache;

    @Override
    public void init(DataStreamLineManager context) {
        this.context = context;
        this.dataStreamCache = context.getCache();
    }

    @Override
    public void process(DataStreamAdapter dataStreamAdapter) throws UnsupportedEncodingException {
        this.dataStreamCache.setState(TestState.LOOK);
        this.dataStreamCache.setMatchProcessor(this);
        byte[] block = dataStreamAdapter.getBlock();
        if (block.length == 0) {
            this.next(false);
        }
        this.dataStreamCache.setDataBuff(block);
        if (this.dataStreamCache.dataSize() < 3) {
            this.next(false);
        }
        if (this.dataStreamCache.getByte(0) != 0x68 || this.dataStreamCache.getByte(2) != 0x68) {
            this.dataStreamCache.setState(TestState.ERROR);
            this.next(false);
        }
        // 报文正文长度,第2个字节
        byte[] dataAreaLenBuff = new byte[1];
        dataAreaLenBuff[0] = this.dataStreamCache.getByte(1);
        int contentLen = dataAreaLenBuff[0] < 0 ? dataAreaLenBuff[0] + 256 : dataAreaLenBuff[0];
        int datagramSize = 5 + contentLen;
        if (this.dataStreamCache.dataSize() < datagramSize) {
            this.next(false);
        }
        this.dataStreamCache.setDatagramSize(datagramSize);
        byte[] datagramBuff = this.dataStreamCache.getBytes(datagramSize);
        this.dataStreamCache.setDatagramBuff(datagramBuff);
        int count = 0;
        byte[] packetHeader = BytesHelp.subBytes(datagramBuff, count, 3);
        this.dataStreamCache.putValue(DataStreamCacheMetadata.METADATA_PACKET_HEADER.getName(), packetHeader);
        count += 3;
        if (contentLen >= 7) {
            //控制域 第4个字节
            byte[] ca = this.dataStreamCache.getBytes(count, 1);
            count += 1;
            //传输方向位 0 下行报文 ，1 上行报文（RTU上报）
            int dir = BytesHelp.bcdToInt(ca[0], 7, 7);
            this.dataStreamCache.putValue(DataStreamCacheMetadata.METADATA_SZY_CA_DIR.getName(), dir);
            //拆分标志位 0 单帧，1 多帧（控制域后增加一个字节，表示帧计数,255-1 ,1为最后一帧）
            int div = BytesHelp.bcdToInt(ca[0], 6, 6);
            this.dataStreamCache.putValue(DataStreamCacheMetadata.METADATA_SZY_CA_DIV.getName(), div);
            //重试发送计数，可设定一个值，发一次减1，0时发送失败
            int fcb = BytesHelp.bcdToInt(ca[0], 5, 4);
            this.dataStreamCache.putValue(DataStreamCacheMetadata.METADATA_SZY_CA_FCB.getName(), fcb);
            //控制功能码
            int funCode = BytesHelp.bcdToInt(ca[0], 3, 0);
            this.dataStreamCache.putValue(DataStreamCacheMetadata.METADATA_SZY_CA_CODE.getName(), funCode);
            if (div == 1) {
                byte[] divsBuff = this.dataStreamCache.getBytes(count, 1);
                int divs = divsBuff[0] < 0 ? divsBuff[0] + 256 : divsBuff[0];
                this.dataStreamCache.putValue(DataStreamCacheMetadata.METADATA_SZY_CA_DIV_COUNT.getName(), divs);
                count += 1;
            }
            //地址域
            byte[] rtuCodeByte = BytesHelp.subBytes(datagramBuff, count, 5);
            count += 5;
            dataStreamCache.putValue(DataStreamCacheMetadata.METADATA_RTU_CODE.getName(), rtuCodeByte);
            //应用功能码
            byte[] command = BytesHelp.subBytes(datagramBuff, count, 1);
            count += 1;
            dataStreamCache.putValue(DataStreamCacheMetadata.METADATA_SZY_AFN.getName(), command);
            int headLen = 7;
            if (div == 1) {
                headLen += 1;
            }
            if (contentLen - headLen > 0) {
                //报文正文
                byte[] dataArea = BytesHelp.subBytes(datagramBuff, count, contentLen - headLen);
                dataStreamCache.putValue(DataStreamCacheMetadata.METADATA_DATA_AREA.getName(), dataArea);
                count += dataArea.length;
            }
        }
        //帧校验 包括控制域、地址域、用户数据
        byte[] crc = BytesHelp.subBytes(datagramBuff, count, 1);
        dataStreamCache.putValue(DataStreamCacheMetadata.METADATA_CRC.getName(), crc);
        count += 1;
        //结束字符
        byte[] endflag = BytesHelp.subBytes(datagramBuff, count, 1);
        count += 1;
        if (endflag[0] == 0x16) {
            dataStreamCache.setReadSize(dataStreamCache.getDatagramSize());
            dataStreamCache.setState(TestState.MATHCE);
            this.next(true);
        } else {
            dataStreamCache.setState(TestState.ERROR);
            this.next(false);
        }
    }

    @Override
    public void close(DataStreamAdapter dataStreamAdapter) {

    }

    @Override
    public void batchComplete(DataStreamAdapter dataStreamAdapter) {
        if (dataStreamCache.getState() == TestState.ERROR) {
            int size = this.dataStreamCache.dataSize();
            int count = 0;
            for (int i = 1; i < size; i++) {
                byte v = dataStreamCache.getByte(i);
                if (v == 0x68) {
                    count = i;
                    break;
                }
            }
            if (count > 0) {
                dataStreamCache.setReadSize(count);
            } else {
                dataStreamCache.setReadSize(size);
            }
        }
    }

    @Override
    public List<Map<String, Object>> sink(DataStreamAdapter dataStreamAdapter) {
        return null;
    }

}
