using System;
using System.Net;
using System.Timers;
using System.Reflection;
using System.Net.Sockets;

using FilterAPI.Networking;
using System.Threading;

namespace FilterZone.ZoneNetworking
{
    internal class ZoneServer : Client, IDisposable
    {
        public ZoneClient Client;

        public FiestaCrypto Crypto;

        public ZoneServer(ZoneClient TClient)
            : base(IPAddress.Parse(Program.Auth.ConfigValues[String.Format("Zone{0}ConnectIP", Program.ZoneID)]), Convert.ToInt32(Program.Auth.ConfigValues[String.Format("Zone{0}ConnectPort", Program.ZoneID)])) { Client = TClient; }

        public void BanAndWipe(String Reason, Boolean WipeMoney = false)
        {
            if (Client.sID != String.Empty && Client.nUserNo != -1)
            {
                using (var LocalPacket = new Packet(4, 7))
                {
                    LocalPacket.PacketWriter.Write(Client.sID);
                    LocalPacket.PacketWriter.Write(false);
                    LocalPacket.PacketWriter.Write("");
                    LocalPacket.PacketWriter.Write("");

                    Program.LocalClient.SendPacket(LocalPacket);

                    Program.SQL.InserttFilterBan(Client.nUserNo, Reason);
                }
            }
        }

        public void SendPacket(Packet ClientPacket)
        {
            if (IsConnected != 0) { return; }

            Byte[] PacketBuffer;

            ClientPacket.ToArray(Crypto, out PacketBuffer);

            Send(PacketBuffer);
        }

        public override void Connected() { Receive(); }

        public override void ConnectFailed(Exception Error)
        {
            Disconnect();

            Client.Disconnect();
        }

        public override void Received(Byte[] Buffer)
        {
            if (IsConnected != 0) { return; }

            if (Buffer != null && Buffer.Length >= 2)
            {
                using (var ServerPacket = new Packet(Buffer))
                {
                    if (!ServerPacket.SetHeaderAndType()) { Disconnect(); }
                    else if (Program.ZoneHandlers.HasHandler(ServerPacket.Header, ServerPacket.Type))
                    {
                        try
                        {
                            MethodInfo PacketMethod = Program.ZoneHandlers.GetHandler(ServerPacket.Header, ServerPacket.Type);

                            Action PacketAction = Program.ZoneHandlers.GetAction(PacketMethod, this, ServerPacket);
                            PacketAction();
                        }
                        catch (Exception Error)
                        {
                            Client.SendPacket(ServerPacket);

                            Program.SendConsoleText(ConsoleColor.Red, String.Format("Header: {0} || Type: {1}\n{2}", ServerPacket.Header, ServerPacket.Type, Error.ToString()));
                        }
                    }
                    else { Client.SendPacket(ServerPacket); }
                }
            }
            else { Disconnect(); }
        }

        public override void Disconnected()
        {
            if (Program.ZoneClients.ContainsKey(Client.ClientGUID)) { Program.ZoneClients.Remove(Client.ClientGUID); }

            Crypto = null;

            if (Client != null && Client.IsConnected != 0) { Client.Disconnect(); }
        }
    }
}
