using System;
using System.Net;
using System.Net.Sockets;

namespace FilterAPI.Networking
{
    public abstract class Listener
    {
        private Socket ListenSocket;
        private IPEndPoint ListenEndPoint;

        public Listener(Int32 Backlog, Int32 Port)
        {
            ListenEndPoint = new IPEndPoint(IPAddress.Any, Port);

            ListenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            ListenSocket.Bind(ListenEndPoint);
            ListenSocket.Listen(Backlog);
        }

        public Listener(IPAddress BindIP, Int32 Backlog, Int32 Port)
        {
            ListenEndPoint = new IPEndPoint(BindIP, Port);

            ListenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            ListenSocket.Bind(ListenEndPoint);
            ListenSocket.Listen(Backlog);
        }

        public void Accept() { ListenSocket.BeginAccept(new AsyncCallback(Accepted), null); }
        
        private void Accepted(IAsyncResult AsyncResult)
        {
            Accept();

            Socket AcceptedSocket = null;

            try { AcceptedSocket = ListenSocket.EndAccept(AsyncResult); }
            catch
            {
                if (AcceptedSocket != null)
                {
                    AcceptedSocket.Close();
                    AcceptedSocket.Dispose();
                }

                return;
            }

            IPEndPoint AcceptedEndPoint = (IPEndPoint)AcceptedSocket.RemoteEndPoint;

            NewSocket(AcceptedSocket, AcceptedEndPoint);
        }

        public abstract void NewSocket(Socket AcceptedSocket, IPEndPoint AcceptedEndPoint);
    }
}
