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

import java.nio.ByteBuffer;

/**
 * 规范异常值处理辅助：GB/T 32960.3 约定 {@code 0xFE}/{@code 0xFFFE}/{@code 0xFFFFFFFE} 为异常，
 * {@code 0xFF}/{@code 0xFFFF}/{@code 0xFFFFFFFF} 为无效。本类把字段读取 + 异常检查封装起来，
 * 异常或无效时返回 {@code null}，让 record 字段保持 {@link Integer}/{@link Double} 装箱类型。
 */
public final class ValueDecoder {

    private ValueDecoder() {}

    // ------------ 1 字节无符号 ------------

    public static Integer u8(ByteBuffer buf) {
        int v = buf.get() & 0xFF;
        if (v == 0xFE || v == 0xFF) return null;
        return v;
    }

    /** 原始值，不做异常处理（状态位等不能以 null 表达时用此方法）。 */
    public static int u8raw(ByteBuffer buf) {
        return buf.get() & 0xFF;
    }

    // ------------ 2 字节无符号大端 ------------

    public static Integer u16(ByteBuffer buf) {
        int v = buf.getShort() & 0xFFFF;
        if (v == 0xFFFE || v == 0xFFFF) return null;
        return v;
    }

    public static int u16raw(ByteBuffer buf) {
        // 仅用于长度、数量、bitmask 等协议控制字段；业务测量值应优先走 u16/scaledU16。
        return buf.getShort() & 0xFFFF;
    }

    // ------------ 4 字节无符号大端 ------------

    public static Long u32(ByteBuffer buf) {
        long v = buf.getInt() & 0xFFFFFFFFL;
        if (v == 0xFFFFFFFEL || v == 0xFFFFFFFFL) return null;
        return v;
    }

    public static long u32raw(ByteBuffer buf) {
        // 仅用于故障码、标志位等需要保留全部 bit 的字段。
        return buf.getInt() & 0xFFFFFFFFL;
    }

    // ------------ 业务标度辅助 ------------

    /** 读 u16，scale 后返回（例如 0.1 转换）。异常/无效返回 null。 */
    public static Double scaledU16(ByteBuffer buf, double scale) {
        Integer raw = u16(buf);
        return raw == null ? null : raw * scale;
    }

    /** 读 u16 + 偏移 + scale。例：读总电流 -> scaledU16WithOffset(buf, 0.1, -1000) */
    public static Double scaledU16WithOffset(ByteBuffer buf, double scale, double offset) {
        Integer raw = u16(buf);
        return raw == null ? null : raw * scale + offset;
    }

    public static Double scaledU32(ByteBuffer buf, double scale) {
        Long raw = u32(buf);
        return raw == null ? null : raw * scale;
    }

    public static Double scaledU32WithOffset(ByteBuffer buf, double scale, double offset) {
        Long raw = u32(buf);
        return raw == null ? null : raw * scale + offset;
    }

    /** 温度字段：原始值 - 40 ℃，范围 -40~+210。 */
    public static Integer tempOffset40(ByteBuffer buf) {
        Integer raw = u8(buf);
        return raw == null ? null : raw - 40;
    }
}
