package com.njzscloud.common.localizer.jt808.message;

import cn.hutool.core.util.ReflectUtil;
import com.njzscloud.common.core.jackson.Jackson;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 * JT808协议消息实体类
 * 用于存储解析后的JT808协议消息内容
 */
@Getter
@Setter
@Slf4j
@Accessors(chain = true)
public class JT808Message {
    // 消息ID (2字节)
    private int messageId;
    // 消息体属性 (2字节)
    private int messageBodyProps;
    // 终端手机号 (6字节, BCD编码)
    private String terminalPhone;
    // 消息流水号 (2字节)
    private int flowId;
    // 消息包封装项 (可选, 当消息体属性中分包标志为1时存在)
    private PackageInfo packageInfo;
    // 消息体
    // private ByteBuf messageBody;
    private byte[] messageBody;
    // 校验码 (1字节)
    private byte checkCode;

    public JT808Message() {
    }

    // 从消息体属性中获取消息体长度
    public int getMessageBodyLength() {
        return messageBodyProps & 0x3FF;
    }

    public List<Integer> getBodyBytes() {
        if (messageBody == null || messageBody.length == 0) {
            return null;
        }
        ArrayList<Integer> integers = new ArrayList<>(messageBody.length);
        for (byte b : messageBody) {
            integers.add((int) b);
        }
        return integers;
    }

    // 从消息体属性中获取是否分包
    public boolean isPackaged() {
        return (messageBodyProps & 0x4000) != 0;
    }

    // 从消息体属性中获取加密方式
    public int getEncryptionType() {
        return (messageBodyProps >> 10) & 0x07;
    }

    @Override
    public String toString() {
        return Jackson.toJsonStr(this);
    }

    public <T> T parseMessageBody(Class<T> clazz) {
        if (messageBody == null || messageBody.length == 0) {
            return null;
        }
        return ReflectUtil.newInstance(clazz, (Object) this.messageBody);
    }

    // 消息包封装项内部类
    @Setter
    @Getter
    @Accessors(chain = true)
    public static class PackageInfo {
        // 消息总包数 (2字节)
        private int totalPackages;
        // 当前包序号 (2字节)
        private int currentPackageNo;
    }

}
