package com.lingniu.ingest.protocol.jt1078.media;

import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.CorruptedFrameException;

final class Jt1078RtpPacketParser {

    static final int MAGIC = 0x30316364;
    static final int HEADER_LEN = 28;

    private Jt1078RtpPacketParser() {}

    static Jt1078RtpPacket parse(ByteBuf in) {
        int magic = in.readInt();
        if (magic != MAGIC) {
            throw new CorruptedFrameException("jt1078 invalid magic: 0x" + Integer.toHexString(magic));
        }
        int sequence = in.readUnsignedShort();
        String sim = readBcd(in, 6);
        int channelId = in.readUnsignedByte();
        int dataAndPacketType = in.readUnsignedByte();
        // 高 4 位是数据类型，低 4 位是分包类型；归档 key 需要二者共同区分。
        int dataType = (dataAndPacketType >>> 4) & 0x0F;
        int packetType = dataAndPacketType & 0x0F;
        long timestamp = in.readLong();
        in.skipBytes(4);
        int bodyLength = in.readUnsignedShort();
        if (bodyLength > in.readableBytes()) {
            throw new CorruptedFrameException("jt1078 body length exceeds readable bytes: "
                    + bodyLength + " > " + in.readableBytes());
        }
        byte[] payload = new byte[bodyLength];
        in.readBytes(payload);
        return new Jt1078RtpPacket(sequence, sim, channelId, dataType, packetType, timestamp, payload);
    }

    static String peekSim(ByteBuf in) {
        if (in == null || in.readableBytes() < HEADER_LEN || in.getInt(in.readerIndex()) != MAGIC) {
            return "";
        }
        // UDP/TCP 解码器在完整 parse 前先取 SIM，用于日志和初步身份定位；不移动 readerIndex。
        StringBuilder sb = new StringBuilder(12);
        int simOffset = in.readerIndex() + 6;
        for (int i = 0; i < 6; i++) {
            int b = in.getUnsignedByte(simOffset + i);
            sb.append((b >>> 4) & 0x0F);
            sb.append(b & 0x0F);
        }
        return sb.toString();
    }

    private static String readBcd(ByteBuf in, int len) {
        StringBuilder sb = new StringBuilder(len * 2);
        for (int i = 0; i < len; i++) {
            int b = in.readUnsignedByte();
            sb.append((b >>> 4) & 0x0F);
            sb.append(b & 0x0F);
        }
        return sb.toString();
    }
}
