package cn.muchinfo.rma.netcore.packet;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;

/**
 *  4.0 行情报文协议(Len >= 15 byte，大端字节序)
 *  Header          byte    1   包头  0xFF
 *  Length          UInt32  4   长度
 *  mainClassNumber byte    1   大类号
 *  subClassNumber  UInt16  2   小类号
 *  SerialNumber    UInt32  4   流水号
 *  Mode            byte    1   内容类型（0:ProtoBuff; 1:Json; 2:Zip+ProtoBuff）
 *  Version         byte    1   版本号
 *  Content         byte[]  n   数据体 心跳数据体长度为0，目前不对4.0（行情）报文进行加解密
 *  End             byte    1   包尾  0x0
 */
public class Packet40 {
    /** 包头 */
    public byte header;
    /** 包长度 */
    public int packageLength;
    /** 大类（服务端会自动变成回复的大类号） */
    public byte mainClassNumber;
    /** 小类 */
    public short subClassNumber;
    /** 流水号 */
    public int serialNumber;
    /** 内容类型 */
    public byte mode;
    /** 版本号 */
    public byte version;
    /** 数据体 */
    public byte[] content;
    /** 包尾 */
    public byte end;

    /**
     * 待发送报文的构造函数
     * @param mainClassNumber 大类号
     * @param subClassNumber 小类号
     * @param content 报文内容
     */
    public Packet40(byte mainClassNumber, short subClassNumber, byte[] content) {
        this.header = (byte)0xFF;
        this.mainClassNumber = mainClassNumber;
        this.subClassNumber = subClassNumber;
        this.content = content;
    }

    /**
     * 使用接收报文的构造函数
     * @param bytes 接收报文
     */
    public Packet40(byte[] bytes) {
        if (bytes.length >= 15) {
            this.header = bytes[0];
            this.packageLength = ByteBuffer.wrap(bytes, 1, 4).order(ByteOrder.BIG_ENDIAN).getInt();
            this.mainClassNumber = bytes[5];
            this.subClassNumber = ByteBuffer.wrap(bytes, 6, 2).order(ByteOrder.BIG_ENDIAN).getShort();
            this.serialNumber = ByteBuffer.wrap(bytes, 8, 4).order(ByteOrder.BIG_ENDIAN).getInt();
            this.mode = bytes[12];
            this.version = bytes[13];
            if (bytes.length > 15) {
                this.content = Arrays.copyOfRange(bytes, 14, bytes.length - 1);
            }
            this.end = bytes[bytes.length - 1];
        }
    }

    /**
     * 获取可发送的包数据流
     * @return 包数据流
     */
    public byte[] getBytes() {
        if (null != this.content) {
            this.packageLength = this.content.length + 15;
        } else {
            this.packageLength = 15;
        }

        byte[] rst = new byte[this.packageLength];
        int pos = 0;
        // 包头
        rst[pos] = this.header;
        pos++;
        // 包长度
        byte[] tmpBytes = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN).putInt(this.packageLength).array();
        System.arraycopy(tmpBytes, 0, rst, pos, tmpBytes.length);
        pos += 4;
        // 大类号
        rst[pos] = this.mainClassNumber;
        pos++;
        // 小类号
        tmpBytes = ByteBuffer.allocate(2).order(ByteOrder.BIG_ENDIAN).putShort(this.subClassNumber).array();
        System.arraycopy(tmpBytes, 0, rst, pos, tmpBytes.length);
        pos += 2;
        // 流水号
        tmpBytes = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN).putInt(this.serialNumber).array();
        System.arraycopy(tmpBytes, 0, rst, pos, tmpBytes.length);
        pos += 4;
        // 内容类型
        rst[pos] = this.mode;
        pos++;
        // 版本号
        rst[pos] = this.version;
        pos++;
        // 数据体
        if (null != this.content)
            System.arraycopy(this.content, 0, rst, pos, this.content.length);
        // 包尾
        rst[this.packageLength - 1] = this.end;

        return rst;
    }
}
