using StandardScene.Magnetic.Protocol;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace StandardScene.Magnetic.Tests.TestHelpers
{
    internal sealed class TestUdpCar : IFass2UdpCar, IDisposable
    {
        private readonly UdpClient _ackListener;
        private readonly object _syncRoot = new object();

        public TestUdpCar(ushort vehicleCode, int remotePort)
        {
            VehicleCode = vehicleCode;
            RemotePort = remotePort;
            _ackListener = new UdpClient(new IPEndPoint(IPAddress.Loopback, remotePort));
            _ackListener.Client.ReceiveTimeout = 500;
        }

        public ushort VehicleCode { get; }

        public string RemoteAddress => "127.0.0.1";

        public int RemotePort { get; }

        public List<Fass2StateReport> Reports { get; } = new List<Fass2StateReport>();

        public void OnUdpStateReceived(Fass2StateReport report)
        {
            lock (_syncRoot)
            {
                Reports.Add(report);
            }
        }

        public byte[] WaitForAck(int timeoutMs = 2000)
        {
            var deadline = Environment.TickCount64 + timeoutMs;
            while (Environment.TickCount64 < deadline)
            {
                try
                {
                    var remote = new IPEndPoint(IPAddress.Any, 0);
                    return _ackListener.Receive(ref remote);
                }
                catch (SocketException)
                {
                    Thread.Sleep(20);
                }
            }

            return null;
        }

        public void Dispose()
        {
            _ackListener?.Close();
            _ackListener?.Dispose();
        }
    }
}
