using System;

namespace StandardScene.Fass2Simulator
{
    public sealed class Fass2SimVehicle
    {
        private readonly object _syncRoot = new object();

        public Fass2SimVehicle(Fass2SimConfig config)
        {
            Car = config.VehicleCode;
            Length = config.CarLength;
            Width = config.CarWidth;
            BatteryCharge = config.BatteryCharge;
            BatteryHealth = 100;
            BatteryVoltage = 480;
            State = config.InitialState;
            Node = config.InitialNode;
            Speed = 500;
        }

        public ushort Car { get; }
        public ushort Length { get; set; }
        public ushort Width { get; set; }
        public byte BatteryCharge { get; set; }
        public byte BatteryHealth { get; set; }
        public ushort BatteryCurrent { get; set; }
        public ushort BatteryVoltage { get; set; }
        public ushort HeadingAngle { get; set; }
        public byte State { get; set; }
        public ulong Alarm { get; set; }
        public ulong Task { get; set; }
        public byte LastCommand { get; set; }

        public ushort Node { get; set; }
        public ushort Distance { get; set; }
        public byte StartStop { get; set; }
        public byte Direction { get; set; }
        public byte Orientation { get; set; }
        public byte Byroad { get; set; }
        public ushort Speed { get; set; }
        public byte Obstacle { get; set; }
        public byte Audio { get; set; }
        public byte Light { get; set; }
        public byte Charge { get; set; }
        public byte Rest { get; set; }
        public byte Lift { get; set; }
        public byte Clamp { get; set; }
        public byte Tray { get; set; }
        public byte Roll { get; set; }
        public byte Shutdown { get; set; }

        public long StateReportsSent { get; private set; }
        public long CommandsReceived { get; private set; }
        public long AckReceived { get; private set; }
        public DateTime LastAckUtc { get; private set; } = DateTime.MinValue;

        public void RecordStateReportSent()
        {
            lock (_syncRoot)
            {
                StateReportsSent++;
            }
        }

        public void RecordCommandReceived()
        {
            lock (_syncRoot)
            {
                CommandsReceived++;
            }
        }

        public void RecordAckReceived()
        {
            lock (_syncRoot)
            {
                AckReceived++;
                LastAckUtc = DateTime.UtcNow;
            }
        }

        public Fass2SimVehicleSnapshot Snapshot()
        {
            lock (_syncRoot)
            {
                return CopySnapshotUnsafe();
            }
        }

        /// <summary>
        /// 供已持有其它引擎锁的代码路径读取快照，避免与 UI 线程 Snapshot() 争用 _syncRoot 导致死锁。
        /// </summary>
        internal Fass2SimVehicleSnapshot CopySnapshotUnsafe()
        {
            return new Fass2SimVehicleSnapshot
            {
                Car = Car,
                Length = Length,
                Width = Width,
                BatteryCharge = BatteryCharge,
                BatteryHealth = BatteryHealth,
                BatteryCurrent = BatteryCurrent,
                BatteryVoltage = BatteryVoltage,
                HeadingAngle = HeadingAngle,
                State = State,
                Alarm = Alarm,
                Task = Task,
                LastCommand = LastCommand,
                Node = Node,
                Distance = Distance,
                StartStop = StartStop,
                Direction = Direction,
                Orientation = Orientation,
                Byroad = Byroad,
                Speed = Speed,
                Obstacle = Obstacle,
                Audio = Audio,
                Light = Light,
                Charge = Charge,
                Rest = Rest,
                Lift = Lift,
                Clamp = Clamp,
                Tray = Tray,
                Roll = Roll,
                Shutdown = Shutdown,
                StateReportsSent = StateReportsSent,
                CommandsReceived = CommandsReceived,
                AckReceived = AckReceived,
                LastAckUtc = LastAckUtc
            };
        }
    }

    public sealed class Fass2SimVehicleSnapshot
    {
        public ushort Car { get; set; }
        public ushort Length { get; set; }
        public ushort Width { get; set; }
        public byte BatteryCharge { get; set; }
        public byte BatteryHealth { get; set; }
        public ushort BatteryCurrent { get; set; }
        public ushort BatteryVoltage { get; set; }
        public ushort HeadingAngle { get; set; }
        public byte State { get; set; }
        public ulong Alarm { get; set; }
        public ulong Task { get; set; }
        public byte LastCommand { get; set; }
        public ushort Node { get; set; }
        public ushort Distance { get; set; }
        public byte StartStop { get; set; }
        public byte Direction { get; set; }
        public byte Orientation { get; set; }
        public byte Byroad { get; set; }
        public ushort Speed { get; set; }
        public byte Obstacle { get; set; }
        public byte Audio { get; set; }
        public byte Light { get; set; }
        public byte Charge { get; set; }
        public byte Rest { get; set; }
        public byte Lift { get; set; }
        public byte Clamp { get; set; }
        public byte Tray { get; set; }
        public byte Roll { get; set; }
        public byte Shutdown { get; set; }
        public long StateReportsSent { get; set; }
        public long CommandsReceived { get; set; }
        public long AckReceived { get; set; }
        public DateTime LastAckUtc { get; set; }
    }
}
