using LFP_Manager.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LFP_Manager.Function
{
    internal class CsModbusFunction
    {
        static public byte[] MakeWriteRegisterData(ushort devId, ushort writeAddr, short[] writeData)
        {
            if (writeData == null || writeData.Length == 0)
                return Array.Empty<byte>();

            // 부호 확장 없이 캐스팅 (2’s complement 그대로 0..65535 범위로 들어갑니다)
            Span<ushort> regs = writeData.Length <= 16
                ? stackalloc ushort[writeData.Length]
                : new ushort[writeData.Length]; // 길면 힙 사용

            for (int k = 0; k < writeData.Length; k++)
                regs[k] = unchecked((ushort)writeData[k]);

            return MakeWriteRegisterData(devId, writeAddr, regs);
        }
        static private byte[] MakeWriteRegisterData(ushort devId, ushort writeAddr, ReadOnlySpan<ushort> writeData)
        {
            if (writeData.Length <= 0)
                return Array.Empty<byte>();

            const byte Func = 0x10; // PRESET_MULTI_REG
            int regCount = writeData.Length;
            int payloadLen = 7 + regCount * 2;     // CRC 제외 길이
            byte[] frame = new byte[payloadLen + 2];

            int i = 0;
            frame[i++] = (byte)devId;              // Device ID
            frame[i++] = Func;                     // Function Code (0x10)
            frame[i++] = (byte)(writeAddr >> 8);   // Addr Hi
            frame[i++] = (byte)writeAddr;         // Addr Lo
            frame[i++] = (byte)(regCount >> 8);    // Count Hi
            frame[i++] = (byte)regCount;          // Count Lo
            frame[i++] = (byte)(regCount * 2);     // ByteCount

            // 데이터: 각 레지스터를 Hi → Lo 바이트로
            for (int j = 0; j < regCount; j++)
            {
                ushort v = writeData[j];
                frame[i++] = (byte)(v >> 8);
                frame[i++] = (byte)v;
            }

            // CRC (CRCL → CRCH) 부착
            if (!CsCRC16.TryAppendCrcLowHigh(frame, payloadLen, 0))
                return Array.Empty<byte>();

            return frame;
        }

    }
}
