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

namespace Villain.Networking.Packets
{
	public class Listener : IDisposable
	{
		private Socket _socket;

		public Action<Socket> OnConnect;

		private bool _isListening = false;

		~Listener()
		{
			Dispose();
		}

		public void Dispose()
		{
			_isListening = false;

			_socket?.Dispose();
		}

		public void Listen(Int32 port)
		{
			Listen(IPAddress.Any, port);
		}

		public void Listen(string ipAddress, Int32 port)
		{
			Listen(new IPEndPoint(IPAddress.Parse(ipAddress), port));
		}

		public void Listen(IPAddress ipAddress, Int32 port)
		{
			Listen(new IPEndPoint(ipAddress, port));
		}

		public void Listen(IPEndPoint ipEndPoint, int backlog = 10)
		{
			_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
			_socket.NoDelay = true;

			_socket.Bind(ipEndPoint);

			_socket.Listen(backlog);

			_isListening = true;

			BeginAccept();
		}

		private void BeginAccept()
		{
			if (_isListening)
			{
				_socket.BeginAccept(new AsyncCallback(Accept), null);
			}
		}

		private void Accept(IAsyncResult asyncResult)
		{
			Socket clientSocket = _socket.EndAccept(asyncResult);

			BeginAccept();

			OnConnect?.Invoke(clientSocket);
		}
	}
}