using System;
using System.Data;
using System.Linq;

using FilterAPI;
using FilterAPI.Networking;
using FilterAPI.CustomCurrency;

using FilterZone.ZoneNetworking;

namespace FilterZone.ZoneHandlers
{
    internal class Zone9Handle
    {
        [ZonePacketHandler(9, 1)]
        public static void HandleClickEntity(ZoneClient ClientSocket, Packet ClientPacket)
        {
            UInt16 MapObjectID = UInt16.MaxValue;

            ClientSocket.AutoAttacking = false;
            ClientSocket.SendPacketServer(ClientPacket);

            if ((MapObjectID = ClientPacket.PacketReader.ReadUInt16()) != UInt16.MaxValue) { ClientSocket.ClickedMapObjectID = MapObjectID; }
        }

        [ZonePacketHandler(9, 8)]
        public static void HandleUnclickEntity(ZoneClient ClientSocket, Packet ClientPacket)
        {
            ClientSocket.AutoAttacking = false;
            ClientSocket.SendPacketServer(ClientPacket);
            ClientSocket.ClickedMapObjectID = UInt16.MaxValue;
        }

        [ZonePacketHandler(9, 12)]
        public static void HandleLevelUp(ZoneClient ClientSocket, Packet ServerPacket)
        {
            ClientSocket.SendPacketClient(ServerPacket);

            Byte NewLevel = ServerPacket.PacketReader.ReadByte();
            Byte PlayerClass = Program.SQL.GetnClassFromnCharNo(ClientSocket.nCharNo);

            if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureLUCR"]))
            {
                foreach (DataRow Row in Program.LevelUpMobSpawns.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToByte(ItemArray.ItemArray[0]) == NewLevel))
                {
                    for (Int32 Counter = 0; Counter < Convert.ToInt32(Row.ItemArray[2]); Counter++) { Command.Mobbreed(ClientSocket, Convert.ToString(Row.ItemArray[1]), 1, 0, false, 1); }

                    if (Convert.ToString(Row.ItemArray[3]) != "-") { GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", Convert.ToString(Row.ItemArray[3])); }
                }

                foreach (DataRow Row in Program.LevelUpItemSpawns.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToByte(ItemArray.ItemArray[0]) == NewLevel))
                {
                    if (Convert.ToByte(Row.ItemArray[1]) == 0 || Convert.ToByte(Row.ItemArray[1]) == PlayerClass)
                    {
                        Int64 nItemKey = Program.ItemCreator.CreateItem(ClientSocket.nCharNo, Convert.ToUInt16(Row.ItemArray[2]), 2);
                        Byte Class = Convert.ToByte(Program.ItemInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToUInt16(ItemArray.ItemArray[0]) == Convert.ToUInt16(Row.ItemArray[2])).FirstOrDefault().ItemArray[4]);

                        ItemOptions Options = new ItemOptions()
                        {
                            Type = Class,
                            Amount = Convert.ToByte(Row.ItemArray[3]),
                            Upgrade = Convert.ToByte(Row.ItemArray[4]),
                            STR = Convert.ToInt16(Row.ItemArray[5]),
                            END = Convert.ToInt16(Row.ItemArray[6]),
                            DEX = Convert.ToInt16(Row.ItemArray[7]),
                            INT = Convert.ToInt16(Row.ItemArray[8]),
                            SPR = Convert.ToInt16(Row.ItemArray[9]),
                            RunOut = Convert.ToInt64(Row.ItemArray[10]),
                            LeftToUse = Convert.ToInt32(Row.ItemArray[11]),
                            Durability = Convert.ToInt32(Row.ItemArray[12])
                        };

                        Program.ItemCreator.InsertOptions(nItemKey, Options);

                        if (Convert.ToString(Row.ItemArray[13]) != "-") { GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", Convert.ToString(Row.ItemArray[13])); }
                    }
                }

                foreach (DataRow Row in Program.LevelUpAbstates.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToByte(ItemArray.ItemArray[0]) == NewLevel))
                {
                    if (Convert.ToByte(Row.ItemArray[1]) == 0 || Convert.ToByte(Row.ItemArray[1]) == PlayerClass)
                    {
                        DataRow AbstateViewRow = Program.AbStateView.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToUInt16(ItemArray.ItemArray[0]) == Convert.ToUInt16(Row.ItemArray[2])).FirstOrDefault();

                        Int32 Duration = Convert.ToInt32(Row.ItemArray[3]);
                        Byte Effect = Convert.ToByte(Row.ItemArray[4]);

                        if (Duration == 0 && Effect == 0) { Command.SetAbstate(ClientSocket, Convert.ToString(AbstateViewRow.ItemArray[1])); }
                        else if (Duration != 0 && Effect == 0) { Command.SetAbstate(ClientSocket, Convert.ToString(AbstateViewRow.ItemArray[1]), Duration); }
                        else { Command.SetAbstate(ClientSocket, Convert.ToString(AbstateViewRow.ItemArray[1]), Duration, Effect); }
                    }
                }
            }
        }

        [ZonePacketHandler(9, 14)]
        public static void HandleSetHP(ZoneClient ClientSocket, Packet ServerPacket)
        {
            UInt32 HP = ServerPacket.PacketReader.ReadUInt32();

            if (HP == 0)
            {
                if (ClientSocket.TradeWaitAccept)
                {
                    ClientSocket.TradeWaitAccept = false;

                    GlobalPacket.SendRejectTrade(ClientSocket);
                }
                else if (ClientSocket.InTrade)
                {
                    ClientSocket.InTrade = false;

                    GlobalPacket.SendCloseTrade(ClientSocket);
                }
                else if (ClientSocket.IsVending)
                {
                    ClientSocket.Dispose();

                    return;
                }
            }

            ClientSocket.SendPacketClient(ServerPacket);
        }

        [ZonePacketHandler(9, 43)]
        public static void HandleAttackEntityMelee(ZoneClient ClientSocket, Packet ClientPacket)
        {
            ClientSocket.SendPacketServer(ClientPacket);
            ClientSocket.AutoAttacking = true;
        }

        [ZonePacketHandler(9, 50)]
        public static void HandleStopAttackingMelee(ZoneClient ClientSocket, Packet ClientPacket)
        {
            ClientSocket.SendPacketServer(ClientPacket);
            ClientSocket.AutoAttacking = false;
        }

        [ZonePacketHandler(9, 64)]
        public static void HandleUseSkill(ZoneClient ClientSocket, Packet ClientPacket)
        {
            ClientSocket.SendPacketServer(ClientPacket);

            if (ClientSocket.TradeWaitAccept)
            {
                ClientSocket.TradeWaitAccept = false;

                GlobalPacket.SendRejectTrade(ClientSocket);
            }
            else if (ClientSocket.InTrade)
            {
                ClientSocket.InTrade = false;

                GlobalPacket.SendCloseTrade(ClientSocket);
            }

            UInt16 SkillID = UInt16.MaxValue;
            UInt16 MapObjectID = UInt16.MaxValue;

            if ((SkillID = ClientPacket.PacketReader.ReadUInt16()) != UInt16.MaxValue && (MapObjectID = ClientPacket.PacketReader.ReadUInt16()) != UInt16.MaxValue)
            {
                if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureGSP"]))
                {
                    DataRow ActiveSkillRow = Program.ActiveSkill.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToUInt16(ItemArray.ItemArray[0]) == SkillID).FirstOrDefault();

                    if ((Convert.ToByte(ActiveSkillRow.ItemArray[16]) == 1 && Convert.ToByte(ActiveSkillRow.ItemArray[17]) == 0) || (Convert.ToByte(ActiveSkillRow.ItemArray[16]) == 1 && Convert.ToByte(ActiveSkillRow.ItemArray[17]) == 1) || (Convert.ToByte(ActiveSkillRow.ItemArray[16]) == 1 && Convert.ToByte(ActiveSkillRow.ItemArray[17]) == 2) || (Convert.ToByte(ActiveSkillRow.ItemArray[16]) == 1 && Convert.ToByte(ActiveSkillRow.ItemArray[17]) == 3) || (Convert.ToByte(ActiveSkillRow.ItemArray[16]) == 2 && Convert.ToByte(ActiveSkillRow.ItemArray[17]) == 2))
                    {
                        if (MapObjectID != ClientSocket.MapObjectID)
                        {
                            ClientSocket.Dispose();

                            return;
                        }
                    }
                    else if ((Convert.ToByte(ActiveSkillRow.ItemArray[16]) == 7 && Convert.ToByte(ActiveSkillRow.ItemArray[17]) == 7))
                    {
                        if (Program.ZoneClients.Where(MOID => MOID.Value.MapObjectID == MapObjectID).FirstOrDefault().Value == null)
                        {
                            ClientSocket.Dispose();

                            return;
                        }
                    }
                }
            }
        }

        [ZonePacketHandler(9, 71)]
        public static void HandleAttackAnimation(ZoneClient ClientSocket, Packet ServerPacket)
        {
            ClientSocket.SendPacketClient(ServerPacket);

            UInt16 MapObjectID = ServerPacket.PacketReader.ReadUInt16();

            if (ClientSocket.TradeMapObjectID == MapObjectID)
            {
                if (ClientSocket.TradeWaitAccept)
                {
                    ClientSocket.TradeWaitAccept = false;

                    GlobalPacket.SendRejectTrade(ClientSocket);
                }
                else if (ClientSocket.InTrade)
                {
                    ClientSocket.InTrade = false;

                    GlobalPacket.SendCloseTrade(ClientSocket);
                }
            }
        }

        [ZonePacketHandler(9, 72)]
        public static void HandleAttackDamage(ZoneClient ClientSocket, Packet ServerPacket)
        {
            UInt16 AttackMapObjectID = ServerPacket.PacketReader.ReadUInt16();
            UInt16 TargetMapObjectID = ServerPacket.PacketReader.ReadUInt16();
            Byte IsCrit = ServerPacket.PacketReader.ReadByte();
            UInt16 Damage = ServerPacket.PacketReader.ReadUInt16();
            UInt32 HPLeft = ServerPacket.PacketReader.ReadUInt32();

            if (ClientSocket.TradeMapObjectID == AttackMapObjectID || ClientSocket.TradeMapObjectID == TargetMapObjectID)
            {
                if (ClientSocket.TradeWaitAccept)
                {
                    ClientSocket.TradeWaitAccept = false;

                    GlobalPacket.SendRejectTrade(ClientSocket);
                }
                else if (ClientSocket.InTrade)
                {
                    ClientSocket.InTrade = false;

                    GlobalPacket.SendCloseTrade(ClientSocket);
                }
            }

            if (AttackMapObjectID == ClientSocket.MapObjectID)
            {


                //GlobalPacket.SendShoutMessageServer(ClientSocket.Client, "Server", "You hit {0} (IsCrit: {1}) on {2} it has {3} HP left.", Damage, IsCrit == 17 ? "Yes" : "No", TargetMapObjectID, HPLeft);
            }

            ClientSocket.SendPacketClient(ServerPacket);
        }

        [ZonePacketHandler(9, 74)]
        public static void HandleDieAnimation(ZoneClient ClientSocket, Packet ServerPacket)
        {
            ClientSocket.SendPacketClient(ServerPacket);

            UInt16 MobMapObjectID = ServerPacket.PacketReader.ReadUInt16();
            UInt16 KillerMapObjectID = ServerPacket.PacketReader.ReadUInt16();

            MapObject MO;

            if (MobMapObjectID == ClientSocket.ClickedMapObjectID) { ClientSocket.AutoAttacking = false; }

            if ((MO = ClientSocket.MapObjects.ToArray().Where(MOID => MOID.MapObjectID == MobMapObjectID).FirstOrDefault()) != null && KillerMapObjectID == ClientSocket.MapObjectID)
            {
                foreach (DataRow Row in Program.MobCurrencies.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToUInt16(ItemArray.ItemArray[0]) == MO.MobID))
                {
                    Currency C = Program.Currencies.Currencies.Where(CurrencyID => CurrencyID.CurrencyID == Convert.ToByte(Row[1])).FirstOrDefault();

                    String Type = C.IsCharacter ? "nCharNo" : "nUserNo";
                    Int32 Value = C.IsCharacter ? ClientSocket.nCharNo : ClientSocket.nUserNo;

                    Program.SQL.AddAmountForCC(C.TableName, Convert.ToInt64(Row[2]), Type, Value);

                    if (Convert.ToBoolean(Row[3])) { GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You obtained {0}x\"{1}\" for killing 1x\"{2}\".", Row[2], C.CurrencyName, Program.MobInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToUInt16(ItemArray.ItemArray[0]) == MO.MobID).FirstOrDefault().ItemArray[2]); }
                }

                DataRow MobDeathSpawnRow;

                if ((MobDeathSpawnRow = Program.MobDeathSpawn.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToUInt16(ItemArray.ItemArray[0]) == MO.MobID).FirstOrDefault()) != null)
                {
                    for (Byte Counter = 0; Counter < Convert.ToByte(MobDeathSpawnRow.ItemArray[2]); Counter++) { Command.Mobbreed(ClientSocket, Convert.ToString(MobDeathSpawnRow.ItemArray[1]), 1, 0, false, 1); }
                }
            }

            if (MO != null) { ClientSocket.MapObjects.Remove(MO); }
        }

        [ZonePacketHandler(9, 78)]
        public static void HandleSkillUsePrepareSelf(ZoneClient ClientSocket, Packet ServerPacket)
        {
            UInt16 MapObjectID = ServerPacket.PacketReader.ReadUInt16();

            if (ClientSocket.TradeMapObjectID == MapObjectID)
            {
                if (ClientSocket.TradeWaitAccept)
                {
                    ClientSocket.TradeWaitAccept = false;

                    GlobalPacket.SendRejectTrade(ClientSocket);
                }
                else if (ClientSocket.InTrade)
                {
                    ClientSocket.InTrade = false;

                    GlobalPacket.SendCloseTrade(ClientSocket);
                }
            }

            ClientSocket.SendPacketClient(ServerPacket);
        }

        [ZonePacketHandler(9, 79)]
        public static void HandleSkillUsePrepareOthers(ZoneClient ClientSocket, Packet ServerPacket)
        {
            UInt16 MapObjectID = ServerPacket.PacketReader.ReadUInt16();

            if (ClientSocket.TradeMapObjectID == MapObjectID)
            {
                if (ClientSocket.TradeWaitAccept)
                {
                    ClientSocket.TradeWaitAccept = false;

                    GlobalPacket.SendRejectTrade(ClientSocket);
                }
                else if (ClientSocket.InTrade)
                {
                    ClientSocket.InTrade = false;

                    GlobalPacket.SendCloseTrade(ClientSocket);
                }
            }

            ClientSocket.SendPacketClient(ServerPacket);
        }
    }
}
