package com.lingniu.ingest.protocol.jsatl12.codec;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

/**
 * 苏标报警附件协议分帧。
 *
 * <p>两种帧并存：
 * <ol>
 *   <li>标准 JT/T 808 帧：以 {@code 0x7e} 为分界，承载 0x1210 / 0x1211 / 0x9212 等信令
 *   <li>数据帧：以 {@code 0x30 0x31 0x63 0x64}（即 ASCII "01cd"）为魔数，后续 4 字节大端长度 + 数据
 * </ol>
 *
 * <p>本 decoder 合并处理：根据第一个字节决定分帧策略，输出带类型标记的 {@link Jsatl12RawFrame}。
 */
public class Jsatl12FrameDecoder extends ByteToMessageDecoder {

    private static final byte[] DATA_MAGIC = {0x30, 0x31, 0x63, 0x64};
    private static final int DEFAULT_MAX_FRAME = 64 * 1024;
    private final int maxFrameLength;

    public Jsatl12FrameDecoder() {
        this(DEFAULT_MAX_FRAME);
    }

    public Jsatl12FrameDecoder(int maxFrameLength) {
        this.maxFrameLength = maxFrameLength <= 0 ? DEFAULT_MAX_FRAME : maxFrameLength;
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
        while (in.readableBytes() >= 1) {
            byte first = in.getByte(in.readerIndex());
            if (first == 0x7e) {
                if (!decodeJtFrame(in, out)) return;
            } else if (first == DATA_MAGIC[0]) {
                if (!decodeDataFrame(in, out)) return;
            } else {
                in.skipBytes(1);
            }
        }
    }

    private boolean decodeJtFrame(ByteBuf in, List<Object> out) {
        if (in.readableBytes() < 2) return false;
        int endIdx = in.indexOf(in.readerIndex() + 1, in.writerIndex(), (byte) 0x7e);
        if (endIdx < 0) {
            if (in.readableBytes() > maxFrameLength) {
                byte[] malformed = new byte[in.readableBytes()];
                in.readBytes(malformed);
                out.add(new Jsatl12RawFrame(Jsatl12RawFrame.Type.MALFORMED, malformed));
                return true;
            }
            return false;
        }
        int len = endIdx - (in.readerIndex() + 1);
        if (len <= 0) {
            in.skipBytes(1);
            return true;
        }
        byte[] raw = new byte[len];
        in.skipBytes(1);
        in.readBytes(raw);
        in.skipBytes(1);
        out.add(new Jsatl12RawFrame(Jsatl12RawFrame.Type.JT_MESSAGE, raw));
        return true;
    }

    private boolean decodeDataFrame(ByteBuf in, List<Object> out) {
        if (in.readableBytes() < DATA_MAGIC.length + 4) return false;
        for (int i = 0; i < DATA_MAGIC.length; i++) {
            if (in.getByte(in.readerIndex() + i) != DATA_MAGIC[i]) {
                in.skipBytes(1);
                return true;
            }
        }
        if (in.readableBytes() < 62) return false;
        // DataPacket 布局：4B magic + 50B 文件名 + 4B offset + 4B length + data
        long dataLen = in.getUnsignedInt(in.readerIndex() + 58);
        if (dataLen > maxFrameLength) {
            int malformedLen = in.readableBytes();
            long declaredTotal = 62L + dataLen;
            if (declaredTotal <= Integer.MAX_VALUE && in.readableBytes() >= declaredTotal) {
                malformedLen = (int) declaredTotal;
            }
            byte[] malformed = new byte[malformedLen];
            in.readBytes(malformed);
            out.add(new Jsatl12RawFrame(Jsatl12RawFrame.Type.MALFORMED, malformed));
            return true;
        }
        int totalFrameLen = 62 + (int) dataLen;
        if (in.readableBytes() < totalFrameLen) return false;
        byte[] frame = new byte[totalFrameLen];
        in.readBytes(frame);
        out.add(new Jsatl12RawFrame(Jsatl12RawFrame.Type.DATA_CHUNK, frame));
        return true;
    }
}
