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

namespace GameServer
{
    class cServer
    {
        public ArrayList Bots = new ArrayList();
        public Hashtable hTable = new Hashtable();
        private Socket ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        public HashSet<int> _ActiveConnections;
        public int _Limit = 0;
        public int _AcceptedConnections = 0;

        private int tID = 0;

        public bool StartServer(int Limit)
        {
            ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _ActiveConnections = new HashSet<int>();
            _Limit = Limit;

            try
            {
                ServerSocket.Bind(new IPEndPoint(IPAddress.Any, Program.ConfigClass.Server_Port));
                ServerSocket.Listen(_Limit);
                ServerSocket.BeginAccept(new AsyncCallback(onAccept), ServerSocket);


                return true;
            }
            catch { }

            return false;
        }

        private void CreateBot()
        {
            if (Bots.Count < 2)
            {
                Socket cSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IPv4);
                int SocketID = 0;

                for (int I = 1; I < _Limit; I++)
                {
                    if (_ActiveConnections.Contains(I) == false)
                    {
                        SocketID = I;
                        break;
                    }
                }

                _ActiveConnections.Add(SocketID);
                _AcceptedConnections++;

                cWRClient objUser = new cWRClient(cSocket, _AcceptedConnections, SocketID, false);
                Bots.Add(objUser);
            }
        }
        private void onAccept(IAsyncResult iAr)
        {
            try
            {
                int SocketID = 0;

                for (int I = 1; I < _Limit; I++)
                {
                    if (_ActiveConnections.Contains(I) == false)
                    {
                        SocketID = I;
                        break;
                    }
                }

                if (SocketID > 0)
                {
                    Socket cSocket = ((Socket)iAr.AsyncState).EndAccept(iAr);
                    if (((IPEndPoint)cSocket.RemoteEndPoint).Address == IPAddress.Parse("46.37.175.96"))
                    {
                     }
                    else
                    {
                        Program.WriteLine("Network", "Accepted connection [" + SocketID + "] from " + cSocket.RemoteEndPoint.ToString().Split(':')[0]);
                        _ActiveConnections.Add(SocketID);
                        _AcceptedConnections++;

                        cWRClient objUser = new cWRClient(cSocket, _AcceptedConnections, SocketID, false);
                        CreateBot();
                    }
                }
            }
            catch { }
            ServerSocket.BeginAccept(new AsyncCallback(onAccept), ServerSocket);
        }

        public void freeSlot(int SocketID)
        {
            if (_ActiveConnections.Contains(SocketID))
            {
                Program.WriteLine("Network","Flagged connection [" + SocketID + "] as free.");
                _ActiveConnections.Remove(SocketID);
            }
        }


        public void SetUpHandlers()
        {
            addFunc(44441, new CP_ISC_LOGIN_PACKET());
            addFunc(91337, new CP_WELCOME_PACKET()); // 24832
            addFunc(25088, new CP_CHARACTER_INFO());
            addFunc(28673, new CP_CHANGE_CHANNEL());
            addFunc(29696, new CP_CHAT());
            addFunc(25600, new CP_PREMIUM_LEFT()); //Unknown Received Packet
            addFunc(28960, new CP_USER_LIST());
            addFunc(29970, new CP_CHANGE_WEAPON());
            addFunc(29440, new CP_CREATE_ROOM());
            addFunc(29504, new CP_LEAVE_ROOM());
            addFunc(29184, new CP_ROOM_LIST());
            addFunc(29456, new CP_JOIN_ROOM());
            addFunc(30000, new CP_CHANGE_ROOM_DATA());
            addFunc(29520, new CP_INVITE());
            addFunc(29505, new CP_ROOM_KICK());
            addFunc(30208, new CP_BUY_WEAPON());//habs schon mal rein gemacht :D
            addFunc(30032, new CP_UNKNOW());
            //addFunc(24576, new CP_LEAVE_SERVER());
            addFunc(30257, new CP_LUCKY_SHOT());
            addFunc(30258, new CP_LUCKY_SHOT_WIN());
            addFunc(25605, new CP_COUPON_EVENT());
            addFunc(25606, new CP_COUPON_BUY());
            addFunc(29984, new CP_PLANT_BOMB());
            addFunc(30720, new CP_CREDITS());
            addFunc(30224, new CP_DELETE_WEAPON());
            addFunc(29488, new CP_SPECTACE_ROOM());
            addFunc(201942, new CP_CHECKSUM());
            addFunc(30230, new CP_BUYCOSTUME());
            addFunc(29971, new CP_CHANGE_COSTUME());
        }

        private void addFunc(int OPC, object Function)
        {
            if (hTable.ContainsKey(OPC) == false)
            {
                hTable.Add(OPC, Function);
            }
            else
            {
                new cLog(C.MSG_ERROR, "Operation Code: " + OPC + " has already an Function!");
            }
        }
    }
}
