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

import com.lingniu.ingest.protocol.gb32960.codec.InfoBlockParser;
import com.lingniu.ingest.protocol.gb32960.codec.ValueDecoder;
import com.lingniu.ingest.protocol.gb32960.model.InfoBlock;
import com.lingniu.ingest.protocol.gb32960.model.ProtocolVersion;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

/**
 * 燃料电池电堆数据 (0x30) —— GB/T 32960.3-2025 §7.2.4.6 表 18/19。变长。
 *
 * <p>V2016 的同 typeCode 厂商扩展由 v2016 包独立处理。
 */
public final class FuelCellStackV2025BlockParser implements InfoBlockParser {

    @Override public ProtocolVersion version() { return ProtocolVersion.V2025; }
    @Override public int typeCode() { return 0x30; }
    @Override public int fixedLength() { return -1; }

    @Override
    public InfoBlock parse(ByteBuffer buf) {
        int stackCount = buf.get() & 0xFF;
        List<InfoBlock.Gb32960V2025.FuelCellStack.Stack> stacks = new ArrayList<>(stackCount);
        for (int i = 0; i < stackCount; i++) {
            int stackNo = buf.get() & 0xFF;
            Double voltage = ValueDecoder.scaledU16(buf, 0.1);
            Double current = ValueDecoder.scaledU16(buf, 0.1);
            Double h2InletPressure = ValueDecoder.scaledU16WithOffset(buf, 0.1, -100.0);
            Double airInletPressure = ValueDecoder.scaledU16WithOffset(buf, 0.1, -100.0);
            Integer airInletTemp = ValueDecoder.tempOffset40(buf);
            int probeCount = buf.getShort() & 0xFFFF;
            List<Integer> temps = new ArrayList<>(probeCount);
            // 坏包 probeCount 过大时只消费剩余可用字节；声明数量仍保存在 stack 对象外层上下文中。
            int safeCount = Math.min(probeCount, buf.remaining());
            for (int k = 0; k < safeCount; k++) {
                temps.add((buf.get() & 0xFF) - 40);
            }
            stacks.add(new InfoBlock.Gb32960V2025.FuelCellStack.Stack(
                    stackNo, voltage, current, h2InletPressure, airInletPressure, airInletTemp, temps));
        }
        return new InfoBlock.Gb32960V2025.FuelCellStack(stackCount, stacks);
    }
}
