// Copyright © 2017-2018 Atomic Software, LLC. All Rights Reserved.
// See LICENSE.md for full license information.

using Atom.Core.Collections;
using Atom.Core.Diagnostics;
using System;
using System.Net;
using System.Net.Sockets;

namespace Atom.Core.Networking
{
    public class Listener
    {
        public static List<Listener> ActiveListeners = new List<Listener>();
        public bool IsShutdown { get; set; }

        private readonly string IPAddress;
        private readonly int Port;
        private readonly Socket Socket;

        public Listener(string ipAddress, int port)
        {
            ActiveListeners.Add(this);

            IPAddress = ipAddress;
            Port = port;
            Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            InitSocket();
        }

        private void InitSocket()
        {
            try
            {
                Socket.Bind(new IPEndPoint(System.Net.IPAddress.Parse(IPAddress), Port));
                Socket.Listen(128);
                WaitForConnectionAttempt();

                Log.Info($"Listener started: {IPAddress}:{Port}");
            }
            catch
            {
                Log.Warning($"Could not start the socket on {IPAddress}:{Port}");
            }
        }

        private void WaitForConnectionAttempt()
        {
            if (IsShutdown)
            {
                return;
            }

            Socket.BeginAccept(ConnectionAttempted, Socket);
        }

        private void ConnectionAttempted(IAsyncResult e)
        {
            if (IsShutdown)
            {
                return;
            }

            var unused = new Client(Socket.EndAccept(e));

            WaitForConnectionAttempt();
        }

        public void Shutdown()
        {
            if (IsShutdown)
            {
                return;
            }

            IsShutdown = true;
            ActiveListeners.Remove(this);

            Socket.Close();
            Socket.Dispose();
        }
    }
}