#if !NETFX_CORE

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

namespace Plane.Communication
{
    /// <summary>
    /// 监听远程主机的 TCP 连接请求并创建 <see cref="TcpServerConnection"/> 实例与它通信。
    /// </summary>
    public class TcpServerConnectionManager : ExceptionThrownEventSource, IDisposable
    {
        private const int TCP_LOCAL_PORT = 5250;

        private static TcpServerConnectionManager _Instance = new TcpServerConnectionManager();

        private bool _disposed;

        private bool _isListening;

        // TODO: 林俊清, 20150909, 从配置文件中获取要监听的 IP 地址和端口号。
        private TcpListener _listener;

        private bool _shouldListen;

        private TcpServerConnectionManager()
        {
        }

        public event EventHandler<ConnectionEstablishedEventArgs> ConnectionEstablished;

        public static TcpServerConnectionManager Instance { get { return _Instance; } }

        public void Dispose()
        {
            if (_disposed)
            {
                return;
            }
            StopListening();
            _disposed = true;
        }

        public bool StartListening()
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(nameof(TcpServerConnectionManager));
            }
            if (_shouldListen && _isListening) return true;
            var address = Dns.GetHostAddresses(Dns.GetHostName()).FirstOrDefault(addr => addr.AddressFamily == AddressFamily.InterNetwork && addr.GetAddressBytes()[0] == 192);
            if (address == null) return false;
            _listener = new TcpListener(address, TCP_LOCAL_PORT);
            try
            {
                _listener.Start();
            }
            catch (Exception ex)
            {
              //  RaiseExceptionThrown(ex);
                return false;
            }
            _shouldListen = true;
            Task.Factory.StartNew(async () =>
            {
                while (_isListening)
                {
                    await Task.Delay(5);
                }
                _isListening = true;
                while (_shouldListen)
                {
                    try
                    {
                        var tcpClient = await _listener.AcceptTcpClientAsync();
                        if (_shouldListen)
                        {
                            ConnectionEstablished?.Invoke(
                                this,
                                new ConnectionEstablishedEventArgs(new TcpServerConnection(tcpClient), (tcpClient.Client.RemoteEndPoint as IPEndPoint).Address.ToString())
                            );
                        }
                    }
                    catch (Exception ex)
                    {
                        RaiseExceptionThrown(ex);
                    }
                }
                _isListening = false;
            });
            return true;
        }

        public void StopListening()
        {
            _shouldListen = false;
            _listener?.Stop();
        }
    }
}

#endif
