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

import com.njzscloud.common.localizer.jt808.message.JT808Message;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

/**
 * JT808协议编码器
 * 将JT808Message对象编码为符合协议规范的字节流
 */
public class JT808Encoder extends MessageToByteEncoder<JT808Message> {
    // 消息起始符和结束符
    private static final byte MSG_DELIMITER = 0x7e;

    @Override
    protected void encode(ChannelHandlerContext ctx, JT808Message msg, ByteBuf out) throws Exception {
        // 1. 创建缓冲区存储消息内容（不含起始符和结束符）
        ByteBuf contentBuf = ctx.alloc().buffer();

        try {
            // 2. 写入消息ID
            contentBuf.writeShort(msg.getMessageId());

            // 3. 写入消息体属性
            contentBuf.writeShort(msg.getMessageBodyProps());

            // 4. 写入终端手机号（BCD编码）
            byte[] phoneBytes = stringToBcd(msg.getTerminalPhone(), 6);
            contentBuf.writeBytes(phoneBytes);

            // 5. 写入消息流水号
            contentBuf.writeShort(msg.getFlowId());

            // 6. 写入消息包封装项（如果需要）
            if (msg.isPackaged() && msg.getPackageInfo() != null) {
                contentBuf.writeShort(msg.getPackageInfo().getTotalPackages());
                contentBuf.writeShort(msg.getPackageInfo().getCurrentPackageNo());
            }

            // 7. 写入消息体
            byte[] messageBody = msg.getMessageBody();
            if (messageBody != null && messageBody.length > 0) {
                contentBuf.writeBytes(messageBody);
            }

            // 8. 计算并写入校验码
            byte checkCode = calculateCheckCode(contentBuf);
            contentBuf.writeByte(checkCode);
            msg.setCheckCode(checkCode);

            // 9. 处理转义
            ByteBuf escapedBuf = handleEscape(contentBuf);

            // 10. 写入起始符
            out.writeByte(MSG_DELIMITER);

            // 11. 写入转义后的内容
            out.writeBytes(escapedBuf);

            // 12. 写入结束符
            out.writeByte(MSG_DELIMITER);
            escapedBuf.release();
        } finally {
            // 释放缓冲区
            if (contentBuf.refCnt() > 0) {
                contentBuf.release();
            }
        }
    }

    /**
     * 处理转义字符
     */
    private ByteBuf handleEscape(ByteBuf buf) {
        ByteBuf out = buf.alloc().buffer(buf.readableBytes() * 2); // 预留足够空间

        buf.resetReaderIndex();
        while (buf.readableBytes() > 0) {
            byte b = buf.readByte();
            if (b == MSG_DELIMITER) {
                out.writeByte(0x7d);
                out.writeByte(0x01);
            } else if (b == 0x7d) {
                out.writeByte(0x7d);
                out.writeByte(0x02);
            } else {
                out.writeByte(b);
            }
        }

        return out;
    }

    /**
     * 计算校验码
     * 校验码 = 消息头 + 消息体 中所有字节的异或
     */
    private byte calculateCheckCode(ByteBuf buf) {
        byte checkCode = 0;
        int readerIndex = buf.readerIndex();

        while (buf.readableBytes() > 0) {
            checkCode ^= buf.readByte();
        }

        buf.readerIndex(readerIndex);
        return checkCode;
    }

    /**
     * 字符串转BCD码
     */
    private byte[] stringToBcd(String str, int length) {
        if (str == null || str.length() == 0) {
            return new byte[length];
        }

        // 补0至偶数长度
        int strLen = str.length();
        if (strLen % 2 != 0) {
            str = "0" + str;
        }

        // 确保不超过指定长度
        if (str.length() > length * 2) {
            str = str.substring(0, length * 2);
        }

        byte[] bcd = new byte[length];
        int index = 0;

        for (int i = 0; i < str.length(); i += 2) {
            if (index >= length) {
                break;
            }

            // 高4位
            byte high = (byte) (Character.digit(str.charAt(i), 16) << 4);
            // 低4位
            byte low = (byte) Character.digit(str.charAt(i + 1), 16);

            bcd[index++] = (byte) (high | low);
        }

        return bcd;
    }
}
