using System;
using System.Text;
using StandardScene.Magnetic.Protocol;

namespace StandardScene.Magnetic.Protocol
{
    /// <summary>
    /// 100B 状态帧编码，供模拟器或测试工具复用，字段布局与 <see cref="Fass2Protocol.ParseState"/> 一致。
    /// </summary>
    public static class Fass2StateCodec
    {
        public static byte[] BuildState(Fass2StateReport report, string carType = "Mag2")
        {
            if (report == null)
            {
                throw new ArgumentNullException(nameof(report));
            }

            var frame = new byte[Fass2Protocol.StateFrameLength];
            frame[0] = Fass2Protocol.Begin;
            frame[1] = report.Command;
            WriteUInt16(frame, 2, report.Car);
            WriteUInt16(frame, 4, report.Length);
            WriteUInt16(frame, 6, report.Width);

            var typeBytes = Encoding.ASCII.GetBytes((carType ?? string.Empty).PadRight(16, '\0'));
            Buffer.BlockCopy(typeBytes, 0, frame, 12, Math.Min(16, typeBytes.Length));

            frame[28] = report.BatteryCharge;
            frame[29] = report.BatteryHealth;
            WriteUInt16(frame, 30, report.BatteryCurrent);
            WriteUInt16(frame, 32, report.BatteryVoltage);
            WriteUInt16(frame, 34, report.HeadingAngle);
            frame[36] = report.State;
            WriteUInt64(frame, 37, report.Alarm);
            WriteUInt64(frame, 45, report.Task);

            var node = report.Node ?? new Fass2NodeMessage();
            Buffer.BlockCopy(node.ToBytes(), 0, frame, 53, 25);

            frame[98] = Fass2Protocol.Xor(frame, 1, 97);
            frame[99] = Fass2Protocol.End;
            return frame;
        }

        private static void WriteUInt16(byte[] buffer, int offset, ushort value)
        {
            var bytes = BitConverter.GetBytes(value);
            buffer[offset] = bytes[0];
            buffer[offset + 1] = bytes[1];
        }

        private static void WriteUInt64(byte[] buffer, int offset, ulong value)
        {
            var bytes = BitConverter.GetBytes(value);
            Buffer.BlockCopy(bytes, 0, buffer, offset, 8);
        }
    }
}
