using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace Orbiter.Multiplayer
{
    public class Listener
    {
        private Thread listener;
        private Server server;
        private bool active;
        private Socket socket;
        private List<IPAddress> banned;
        
        public Listener(Server server)
        {
            this.server = server;
            banned = new List<IPAddress>();
        }
        
        public void Start()
        {
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
            socket.Bind(new IPEndPoint(IPAddress.Any, server.Configuration.Network.TCP));
            socket.Listen(server.Configuration.Network.Backlog);
            active = true;
            listener = new Thread(ListenerThread){IsBackground = true, Priority = ThreadPriority.BelowNormal};
            listener.Start();
        }
        
        public void Stop()
        {
            active = false;
            socket.Close();
            listener.Abort();
            listener.Join();
            //if (!listener.Join(1000))
            //{
            //    listener.Interrupt();
            //    listener.Join();
            //}
        }

        public void Reconfigure()
        {
            if (active) Stop();
            Start();
        }

        private void ListenerThread()
        {
            try
            {
                while (active)
                {
                    Socket s = socket.Accept();
                    IPAddress adr = (s.RemoteEndPoint as IPEndPoint).Address;
                    if ((!server.Locked && !banned.Contains(adr)) || IPAddress.IsLoopback(adr)) server.Map.Add(new Host(s, server));
                    else
                    {
                        s.Send(ASCIIEncoding.UTF8.GetBytes("Server closed!\n"));
                        s.Close();
                    }
                }
            }
            catch (ThreadAbortException){}
            catch (SocketException){}//ex){if (ex.SocketErrorCode != SocketError.Interrupted) throw ex;}}
            finally
            {
                socket.Close();
            }
        }

        public List<IPAddress> Banned
        {
            get { return banned; }
        }
    }
}
