package com.lingniu.ingest.protocol.jt808.codec.parser;

import com.lingniu.ingest.codec.BcdCodec;
import com.lingniu.ingest.protocol.jt808.codec.BodyParser;
import com.lingniu.ingest.protocol.jt808.model.Jt808Body;
import com.lingniu.ingest.protocol.jt808.model.Jt808Header;
import com.lingniu.ingest.protocol.jt808.model.Jt808MessageId;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;

public final class TerminalAttrsBodyParser implements BodyParser {

    @Override
    public int messageId() {
        return Jt808MessageId.TERMINAL_ATTRS_REPORT;
    }

    @Override
    public Jt808Body parse(Jt808Header header, ByteBuffer body) {
        int terminalType = readU16(body);
        String maker = readAscii(body, 5);
        String model = readAscii(body, 20);
        String terminalId = readAscii(body, 7);
        String iccid = readBcd(body, 10);
        String hardwareVersion = readAscii(body, 10);
        String firmwareVersion = readAscii(body, 10);
        int gnssProperty = body.hasRemaining() ? body.get() & 0xFF : 0;
        int commProperty = body.hasRemaining() ? body.get() & 0xFF : 0;
        if (body.hasRemaining()) {
            body.position(body.limit());
        }
        return new Jt808Body.TerminalAttrs(
                terminalType, maker, model, terminalId, iccid, hardwareVersion, firmwareVersion,
                gnssProperty, commProperty);
    }

    private static int readU16(ByteBuffer body) {
        return body.remaining() >= 2 ? body.getShort() & 0xFFFF : 0;
    }

    private static String readAscii(ByteBuffer body, int len) {
        int n = Math.min(len, body.remaining());
        byte[] bytes = new byte[n];
        body.get(bytes);
        if (n < len && body.hasRemaining()) {
            body.position(Math.min(body.limit(), body.position() + (len - n)));
        }
        return new String(bytes, StandardCharsets.US_ASCII).trim();
    }

    private static String readBcd(ByteBuffer body, int len) {
        int n = Math.min(len, body.remaining());
        byte[] bytes = new byte[n];
        body.get(bytes);
        return BcdCodec.decode(bytes).trim();
    }
}
