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

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;

/**
 * 驱动电机数据 (0x02) —— GB/T 32960.3-2016 表 B.16。变长。
 * 1 字节电机个数 + N × 12 字节电机：
 * serialNo(1) state(1) ctrlTempC(1) rpm(2,offset -20000)
 * torque(2,offset -20000,0.1 N·m) motorTempC(1)
 * ctrlVoltageV(2,0.1V) ctrlCurrentA(2,0.1A,offset -1000)。
 */
public final class DriveMotorV2016BlockParser implements InfoBlockParser {

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

    @Override
    public InfoBlock parse(ByteBuffer buf) {
        int count = buf.get() & 0xFF;
        List<InfoBlock.Gb32960V2016.DriveMotor.Motor> motors = new ArrayList<>(count);
        for (int i = 0; i < count; i++) {
            // rpm/torque 在标准里是带偏移的无符号数，先按原始无符号读，再统一减偏移。
            Integer serialNo = ValueDecoder.u8(buf);
            Integer state = ValueDecoder.u8(buf);
            Integer ctrlTempC = ValueDecoder.tempOffset40(buf);
            Integer rawRpm = ValueDecoder.u16(buf);
            Integer rpm = rawRpm == null ? null : rawRpm - 20_000;
            Integer rawTq = ValueDecoder.u16(buf);
            Double torque = rawTq == null ? null : (rawTq - 20_000) * 0.1;
            Integer motorTempC = ValueDecoder.tempOffset40(buf);
            Double ctrlVoltage = ValueDecoder.scaledU16(buf, 0.1);
            Double ctrlCurrent = ValueDecoder.scaledU16WithOffset(buf, 0.1, -1000.0);
            motors.add(new InfoBlock.Gb32960V2016.DriveMotor.Motor(
                    serialNo, state, ctrlTempC, rpm, torque, motorTempC, ctrlVoltage, ctrlCurrent));
        }
        return new InfoBlock.Gb32960V2016.DriveMotor(motors);
    }
}
