using System;
using System.Net;
using System.Timers;
using System.Reflection;
using System.Net.Sockets;
using System.Xml;
using FiestaBot.Instances.Networking;
using FiestaBot.Manager.Handlers;
using System.Collections.Generic;
using System.Security.Policy;
using FiestaBot.Manager.Game;
using FiestaBot.Utilities;

namespace FiestaBot.Manager.Networking
{
    internal class ManagerClient : Client
    {
        public FiestaCrypto Crypto;
        
        public bool InCharSelect = false;
        public byte LastSlot = 0;
        public List<byte> InUseCharSlots;

        public Character Character;
        public List<Character> AllCharacters;

        public ushort ZoneKey = 0;

        public bool InParty = false;
        
        public ManagerClient(IPAddress ConnectIP, int Port) : base(ConnectIP, Port)
        {
            Program.ManagerClient = this;

            InUseCharSlots = new List<byte>();
            AllCharacters = new List<Character>();
        }

        public void SendPacket(Packet ServerPacket)
        {
            if(IsConnected != 0) { return; }
            
            ServerPacket.ToArray(Crypto, out byte[] PacketBuffer);
            ServerPacket.Dispose();

            Send(PacketBuffer);
        }

        public override void Connected()
        {
            Receive();
            Logger.Log(LogType.Socket, "Succesfully connected to world");
        }

        public override void ConnectFailed(SocketException Exception) { }

        public override void Received(byte[] Buffer)
        {
            Packet ClientPacket = new Packet(Buffer);

            if (!ClientPacket.SetHeaderAndType()) { Logger.Log(LogType.World, "Unable to read packet header/type"); }
            else if (Program.ManagerHandlers.HasHandler(ClientPacket.Header, ClientPacket.Type))
            {
                try
                {
                    MethodInfo PacketMethod = Program.ManagerHandlers.GetHandler(ClientPacket.Header, ClientPacket.Type);

                    Action PacketAction = Program.ManagerHandlers.GetAction(PacketMethod, this, ClientPacket);
                    PacketAction();
                }
                catch { Logger.Log(LogType.World, "Unknown packet: {0}:{1}", ClientPacket.Header, ClientPacket.Type); }
            }
            else { Logger.Log(LogType.World, "Unknown packet: {0}:{1}", ClientPacket.Header, ClientPacket.Type); }
        }

        public override void Disconnected()
        {
            Logger.Log(LogType.Socket, "Disconnected from world");
        }
    }
}
