namespace OubHackMS.Servers
{
    using OubHackMS.Core;
    using OubHackMS.Logging;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Net;
    using System.Net.Sockets;
    using System.Reflection;
    using System.Threading;

    internal class Server : LinkedClass
    {
        private IPAddress addr = IPAddress.Any;
        private ManualResetEvent mre = new ManualResetEvent(true);
        private Dictionary<short, PacketHandler> packetHandlers = new Dictionary<short, PacketHandler>();
        private int port = 0xeaf8;
        private Socket serverSocket;

        private void acceptConnections()
        {
            Socket socket = this.serverSocket.Accept();
            new Thread(delegate {
                this.acceptConnections();
                Console.WriteLine("New connection");
            }).Start();
            this.onConnect(socket);
        }

        private void onConnect(Socket socket)
        {
            NetworkStream input = null;
            BinaryReader reader = null;
            try
            {
                socket.ReceiveTimeout = 0x3a98;
                socket.SendTimeout = 0x3a98;
                input = new NetworkStream(socket);
                reader = new BinaryReader(input);
                short key = reader.ReadInt16();
                if (this.packetHandlers.ContainsKey(key))
                {
                    try
                    {
                        this.packetHandlers[key].doWork(input);
                    }
                    catch (Exception exception)
                    {
                        base.parent.Log(Level.LOG_CONSOLE_ERROR, new object[] { string.Concat(new object[] { "Packet ", key, " failed to execute ", exception.ToString() }) });
                    }
                }
            }
            catch (Exception exception2)
            {
                base.parent.Log(Level.LOG_CONSOLE_ERROR, new object[] { "Socket exception : " + exception2.ToString() });
            }
            finally
            {
                if (input != null)
                {
                    input.Close();
                }
                if (reader != null)
                {
                    reader.Close();
                }
                if (socket != null)
                {
                    socket.Close();
                }
            }
        }

        public override void onLink()
        {
            Type[] types = Assembly.GetCallingAssembly().GetTypes();
            for (int i = 0; i < types.Length; i++)
            {
                if (types[i].Namespace == "OubHackMS.Servers.Handlers")
                {
                    PacketHandler handler = (PacketHandler) Activator.CreateInstance(types[i], new object[] { base.parent });
                    this.packetHandlers.Add(handler.sIndex, handler);
                }
            }
            new Thread(delegate {
                try
                {
                    this.serverSocket = new Socket(this.addr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                    this.serverSocket.Bind(new IPEndPoint(this.addr, this.port));
                    this.serverSocket.Listen(0xbb8);
                    this.acceptConnections();
                }
                catch (Exception exception)
                {
                    base.parent.Log(Level.LOG_FILE_ERROR, new object[] { "Server bind exception : " + exception.ToString() });
                    base.parent.Log(Level.LOG_CONSOLE_ERROR, new object[] { "Server bind exception : " + exception.Message });
                }
            }).Start();
        }
    }
}

