#if !NETFX_CORE

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;

namespace Plane.Communication
{
    public class UdpConnection : UdpConnectionBase
    {
        private UdpClient _client;
        private bool _isReceiving;
        private object _receiveLock = new object();
        private string _remoteHostName;
        private int _remotePort;
        private bool _shouldReceive;

        public UdpConnection(string remoteHostName, int remotePort = 5250)
        {
            _remoteHostName = remoteHostName;
            _remotePort = remotePort;
        }

        public override void Close()
        {
            if (IsOpen)
            {
                IsOpen = false;
                _shouldReceive = false;
                _client?.Close();
            }
        }

        public override Task OpenAsync()
        {
            if (!IsOpen)
            {
                IsOpen = true;
                _client = new UdpClient(_remoteHostName, _remotePort);
                StartReceiving();
            }
            return TaskUtils.CompletedTask;
        }

        protected override Task SendAsync(byte[] datagram, int bytes)
        {
            return _client.SendAsync(datagram, bytes);
        }

        private void StartReceiving()
        {
            if (_shouldReceive && _isReceiving)
            {
                return;
            }
            _shouldReceive = true;
            Task.Factory.StartNew(() =>
            {
                lock (_receiveLock)
                {
                    _isReceiving = true;
                    IPEndPoint ep = null;
                    while (_shouldReceive)
                    {
                        try
                        {
                            var data = _client.Receive(ref ep);
                            EnqueueDatagram(data);
                        }
                        catch (Exception ex)
                        {
                            RaiseExceptionThrown(ex);
                            Thread.Sleep(500);
                        }
                    }
                    _isReceiving = false;
                }
            }, TaskCreationOptions.LongRunning);
        }
    }
}

#endif
