using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FiestaBot.Enums;
using FiestaBot.Instances.Networking;
using FiestaBot.Utilities;
using FiestaBot.Zone.Game;
using FiestaBot.Zone.Networking;

namespace FiestaBot.Zone.Handlers
{
    internal class Zone07Handler
    {
        [ZonePacketHandler(7, 6)]
        public static void SpawnPlayer(ZoneClient Socket, Packet Packet)
        {
            Packet.ReadUShort(out ushort ObjectID);
            Packet.ReadString(out string Name, 16);
            Packet.ReadInt(out int X);
            Packet.ReadInt(out int Y);
            Packet.ReadByte(out byte Z); // Rotation
            Packet.ReadByte(out byte State); // Player State (1 & 2 - Player / 3 - Dead / 4 - Resting / 5 - Vendor / 6 - Mounted)
            Packet.ReadByte(out byte Class);

            Position Position = new Position
            {
                MapInx = Socket.Manager.Character.Position.MapInx,
                X = X,
                Y = Y,
                Z = Z
            };

            MapObject Object = new MapObject
            {
                ObjectID = ObjectID,
                Name = Name,
                Position = Position,
                Type = ObjectType.Player,
                PlayerState = (PlayerState)State,
                PlayerClass = (Class)Class
            };

            Socket.ObjectList.Add(Object);

            Logger.Log(LogType.ObjPly, "ObjectID: {0} | Name: {1} | Class: {2} | X: {3} | Y: {4} | Z: {5} | State: {6}", ObjectID, Name, (Class)Class, X, Y, Z, (PlayerState)State);
        }

        [ZonePacketHandler(7, 7)]
        public static void SpawnPlayers(ZoneClient Socket, Packet Packet)
        {
            Packet.ReadByte(out byte TotalPlayers);
            for (int i = 0; i < TotalPlayers; i++)
            {
                Packet.ReadUShort(out ushort ObjectID);
                Packet.ReadString(out string Name, 16);
                Packet.ReadInt(out int X);
                Packet.ReadInt(out int Y);
          	Packet.ReadByte(out byte Z); // Rotation
          	Packet.ReadByte(out byte State); // Player State (1 & 2 - Player / 3 - Dead / 4 - Resting / 5 - Vendor / 6 - Mounted)
                Packet.ReadByte(out byte Class);

                Position Position = new Position
                {
                    MapInx = Socket.Manager.Character.Position.MapInx,
                    X = X,
                    Y = Y,
                    Z = Z
                };

                MapObject Object = new MapObject
                {
                    ObjectID = ObjectID,
                    Name = Name,
                    Position = Position,
                    Type = ObjectType.Player,
                    PlayerState = (PlayerState)State,
                    PlayerClass = (Class)Class
                };

                Socket.ObjectList.Add(Object);

                Logger.Log(LogType.ObjPly, "ObjectID: {0} | Name: {1} | Class: {2} | X: {3} | Y: {4} | Z: {5} | State: {6}", ObjectID, Name, (Class)Class, X, Y, Z, (PlayerState)State);
            }

            Packet.Dispose();
        }

        [ZonePacketHandler(7, 8)]
        public static void SpawnObject(ZoneClient Socket, Packet Packet)
        {
            Packet.ReadUShort(out ushort ObjectID);
            Packet.ReadByte(out byte Visible);
            Packet.ReadUShort(out ushort ID);
            Packet.ReadInt(out int X);
            Packet.ReadInt(out int Y);
            Packet.ReadByte(out byte Z);
            Packet.ReadByte(out byte Gate);
            if (Gate == 1)
            {
                Packet.ReadString(out string MapInx, 12);
                for (int x = 0; x < 40; x++) { Packet.ReadByte(out byte Unk00); }

                Position Position = new Position
                {
                    MapInx = Socket.Manager.Character.Position.MapInx,
                    X = X,
                    Y = Y,
                    Z = Z
                };

                MapObject Object = new MapObject
                {
                    ObjectID = ObjectID,
                    ID = ID,
                    Inx = SHNSearch.FindInxByID(FindType.MobInfo, ID),
                    Name = SHNSearch.FindNameByID(FindType.MobInfo, ID),
                    Position = Position,
                    Type = ObjectType.Gate,
                    GateToInx = MapInx
                };

                Socket.ObjectList.Add(Object);

                Logger.Log(LogType.ObjGate, "ObjectID: {0} | ID: {1} | Name: {2} | X: {3} | Y: {4} | Z: {5} | GateInx: {6} | GateName: {7}", ObjectID, ID, SHNSearch.FindNameByID(FindType.MobInfo, ID), X, Y, Z, MapInx, SHNSearch.FindNameByInx(FindType.MapInfo, MapInx));
            }
            else
            {
                for (int x = 0; x < 52; x++) { Packet.ReadByte(out byte Unk02); }

                Position Position = new Position
                {
                    MapInx = Socket.Manager.Character.Position.MapInx,
                    X = X,
                    Y = Y,
                    Z = Z
                };

                MapObject Object = new MapObject
                {
                    ObjectID = ObjectID,
                    ID = ID,
                    Inx = SHNSearch.FindInxByID(FindType.MobInfo, ID),
                    Name = SHNSearch.FindNameByID(FindType.MobInfo, ID),
                    Position = Position,
                    Type = ObjectType.Mob
                };

                Socket.ObjectList.Add(Object);

                Logger.Log(LogType.ObjMob, "ObjectID: {0} | ID: {1} | Name: {2} | X: {3} | Y: {4} | Z: {5}", ObjectID, ID, SHNSearch.FindNameByID(FindType.MobInfo, ID), X, Y, Z);
            }

            Packet.Dispose();
        }

        [ZonePacketHandler(7, 9)]
        public static void SpawnObjects(ZoneClient Socket, Packet Packet)
        {
            //TODO: Make a list of available objects
            Packet.ReadByte(out byte TotalObjects);
            for (int i = 0; i < TotalObjects; i++)
            {
                Packet.ReadUShort(out ushort ObjectID);
                Packet.ReadByte(out byte Visible);
                Packet.ReadUShort(out ushort ID);
                Packet.ReadInt(out int X);
                Packet.ReadInt(out int Y);
                Packet.ReadByte(out byte Z);
                Packet.ReadByte(out byte Gate);
                if (Gate == 1)
                {
                    Packet.ReadString(out string MapInx, 12);
                    for (int x = 0; x < 40; x++) { Packet.ReadByte(out byte Unk00); }

                    Position Position = new Position
                    {
                        MapInx = Socket.Manager.Character.Position.MapInx,
                        X = X,
                        Y = Y,
                        Z = Z
                    };

                    MapObject Object = new MapObject
                    {
                        ObjectID = ObjectID,
                        ID = ID,
                        Inx = SHNSearch.FindInxByID(FindType.MobInfo, ID),
                        Name = SHNSearch.FindNameByID(FindType.MobInfo, ID),
                        Position = Position,
                        Type = ObjectType.Gate,
                        GateToInx = MapInx
                    };

                    Socket.ObjectList.Add(Object);

                    Logger.Log(LogType.ObjGate, "ObjectID: {0} | ID: {1} | Name: {2} | X: {3} | Y: {4} | Z: {5} | GateInx: {6} | GateName: {7}", ObjectID, ID, SHNSearch.FindNameByID(FindType.MobInfo, ID), X, Y, Z, MapInx, SHNSearch.FindNameByInx(FindType.MapInfo, MapInx));
                }
                else
                {
                    for (int x = 0; x < 52; x++) { Packet.ReadByte(out byte Unk02); }

                    Position Position = new Position
                    {
                        MapInx = Socket.Manager.Character.Position.MapInx,
                        X = X,
                        Y = Y,
                        Z = Z
                    };

                    MapObject Object = new MapObject
                    {
                        ObjectID = ObjectID,
                        ID = ID,
                        Inx = SHNSearch.FindInxByID(FindType.MobInfo, ID),
                        Name = SHNSearch.FindNameByID(FindType.MobInfo, ID),
                        Position = Position,
                        Type = ObjectType.Mob
                    };

                    Socket.ObjectList.Add(Object);

                    Logger.Log(LogType.ObjMob, "ObjectID: {0} | ID: {1} | Name: {2} | X: {3} | Y: {4} | Z: {5}", ObjectID, ID, SHNSearch.FindNameByID(FindType.MobInfo, ID), X, Y, Z);
                }
            }

            Packet.Dispose();
        }

        [ZonePacketHandler(7, 24)]
        public static void Handle724(ZoneClient Socket, Packet Packet)
        {
            //TODO: Find out what this does
            Packet.Dispose();
        }
    }
}
