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

using FilterAPI.Systems;
using FilterAPI.Networking;

using FilterZone.ZoneNetworking;

namespace FilterZone.ZoneHandlers
{
    internal class Zone6Handle
    {
        [ZonePacketHandler(6, 1)]
        public static void HandleSHNHashes(ZoneClient ClientSocket, Packet ClientPacket)
        {
            UInt16 PlayerID = UInt16.MaxValue;
            String sID = String.Empty;

            if (((PlayerID = ClientPacket.PacketReader.ReadUInt16()) != UInt16.MaxValue) && ((sID = ClientPacket.ReadString(16)) != String.Empty))
            {
                ClientSocket.sID = sID;

                if (Program.SQL.sIDTaken(ClientSocket.sID))
                {
                    ClientSocket.nCharNo = Program.SQL.GetnCharNoFromsID(sID);
                    ClientSocket.nUserNo = Program.SQL.GetnUserNoFromsID(sID);

                    ClientSocket.SendPacketServer(ClientPacket);
                }
            }
        }

        [ZonePacketHandler(6, 2)]
        public static void HandleUnk00(ZoneClient ClientSocket, Packet ServerPacket)
        {
            ClientSocket.SendPacketClient(ServerPacket);
            ClientSocket.MapObjectID = ServerPacket.PacketReader.ReadUInt16();
        }

        [ZonePacketHandler(6, 3)]
        public static void HandleClientReady(ZoneClient ClientSocket, Packet ClientPacket)
        {
            if (!ClientSocket.SPMC) { ClientSocket.SPMC = true; }
            else { ClientSocket.ShowPlayers = true; }

            if (Program.RemoveALMapIndexs.ContainsKey(ClientSocket.sMap)) { Program.SQL.SetnAdminLevelFornCharNo(ClientSocket.nCharNo, 0); }
            else { Program.SQL.SetnAdminLevelFornCharNo(ClientSocket.nCharNo, 100); }

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

            GlobalPacket.SendRGB(ClientSocket, Program.R, Program.G, Program.B);

            DataRow MapMaximumRow;

            if ((MapMaximumRow = Program.MapMaximum.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToString(ItemArray.ItemArray[0]) == ClientSocket.sMap).FirstOrDefault()) != null)
            {
                if (Convert.ToBoolean(MapMaximumRow.ItemArray[1]))
                {
                    if (Program.ZoneClients.Values.Where(sMap => sMap.sMap == ClientSocket.sMap).Where(InstanceID => InstanceID.InstanceID == ClientSocket.InstanceID).Count() > Convert.ToByte(MapMaximumRow.ItemArray[2]))
                    {
                        GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "The map you just tried to enter has a maximum of {0} players.", MapMaximumRow.ItemArray[2]);

                        Command.Linkto(ClientSocket, Convert.ToString(MapMaximumRow.ItemArray[3]), Convert.ToInt32(MapMaximumRow.ItemArray[4]), Convert.ToInt32(MapMaximumRow.ItemArray[5]));
                    }
                }
                else
                {
                    if (Program.ZoneClients.Values.Where(sMap => sMap.sMap == ClientSocket.sMap).Count() > Convert.ToByte(MapMaximumRow.ItemArray[2]))
                    {
                        GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "The map you just tried to enter has a maximum of {0} players.", MapMaximumRow.ItemArray[2]);

                        Command.Linkto(ClientSocket, Convert.ToString(MapMaximumRow.ItemArray[3]), Convert.ToInt32(MapMaximumRow.ItemArray[4]), Convert.ToInt32(MapMaximumRow.ItemArray[5]));
                    }
                }
            }

            DateTime dDate;

            Int32 nLuckyNo = Program.SQL.GetnLuckyNo(ClientSocket.nCharNo, out dDate);

            if (DateTime.Now > dDate.AddDays(1) || nLuckyNo == 0)
            {
                nLuckyNo = LuckyNumber.GetRandomNumber();

                Program.SQL.SetnLuckyNo(ClientSocket.nCharNo, nLuckyNo);
            }

            ClientSocket.MapObjects.Clear();

            ClientSocket.MapObjects.Add(new MapObject
            {
                MapObjectID = ClientSocket.MapObjectID,
                sID = ClientSocket.sID
            });

            ClientSocket.ClickedMapObjectID = UInt16.MaxValue;
            ClientSocket.RidingID = UInt16.MaxValue;

            ClientSocket.IsMounted = false;
			// zone exp item rate
            if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureEIR"]))
            {
                Int32 nItemRate;
                Int32 nExpRate;

                if (!Program.SQL.GettMapRate(ClientSocket.sMap, out nItemRate, out nExpRate))
                {
                    Command.ExpBonus(ClientSocket, ClientSocket.sMap, Program.SQL.GetnAmountFromsName("EXP"));
                    Command.ItemBonus(ClientSocket, ClientSocket.sMap, Program.SQL.GetnAmountFromsName("ITEM"));
                }
                else
                {
                    Command.ExpBonus(ClientSocket, ClientSocket.sMap, nExpRate);
                    Command.ItemBonus(ClientSocket, ClientSocket.sMap, nItemRate);
                }
            }
			// zone join message
            if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureJM"]) && !ClientSocket.SentMessages)
            {
                GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "Hello {0} (:. There are currently {1} online (including you) and your lucky number is: {2}.", ClientSocket.sID, Program.SQL.GetOnlineCount(), nLuckyNo);

                ClientSocket.SentMessages = true;
            }

            Byte PlayerClassID = Program.SQL.GetnClassFromnCharNo(ClientSocket.nCharNo);

            if (!Program.SQL.PermissionRowExists(ClientSocket.nCharNo))
            {
                Program.SQL.InserttPermission(ClientSocket.nCharNo);
				// zone character create (something)????
                if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureCCC"]))
                {
                    foreach (DataRow Row in Program.CharacterCreate.Table.Rows)
                    {
                        Byte ClassID = Convert.ToByte(Row.ItemArray[0]);
                        String Type = Convert.ToString(Row.ItemArray[1]);
                        Int32 ID = Convert.ToUInt16(Row.ItemArray[2]);
                        UInt32 Option1 = Convert.ToUInt32(Row.ItemArray[3]);
                        UInt32 Option2 = Convert.ToUInt32(Row.ItemArray[4]);
                        String Message = Convert.ToString(Row.ItemArray[5]);

                        if (ClassID == 0 || PlayerClassID == ClassID)
                        {
                            switch (Type)
                            {
                                case "ABSTATE":
                                    {
                                        DataRow AbStateViewRow = Program.AbStateView.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToInt32(ItemArray.ItemArray[0]) == ID).FirstOrDefault();

                                        Command.SetAbstate(ClientSocket, Convert.ToString(AbStateViewRow.ItemArray[1]), Convert.ToInt32(Option1) * 1000, Convert.ToByte(Option2));

                                        break;
                                    }
                                case "ITEM":
                                    {
                                        DataRow ItemInfoRow = Program.ItemInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToInt32(ItemArray.ItemArray[0]) == ID).FirstOrDefault();

                                        if (Option1 == 0) { Command.Makeitem(ClientSocket, Convert.ToString(ItemInfoRow.ItemArray[1])); }
                                        else { Command.Makeitem(ClientSocket, Convert.ToString(ItemInfoRow.ItemArray[1]), Convert.ToByte(Option1)); }

                                        break;
                                    }
                                case "MOB":
                                    {
                                        DataRow MobInfoRow = Program.MobInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToInt32(ItemArray.ItemArray[0]) == ID).FirstOrDefault();

                                        for (Int32 Counter = 0; Counter < Option1; Counter++) { Command.Mobbreed(ClientSocket, Convert.ToString(MobInfoRow.ItemArray[1]), 1, 0, false, 1); }

                                        break;
                                    }
                                case "SKILL":
                                    {
                                        Command.LearnSkill(ClientSocket, ID);

                                        break;
                                    }
                                case "PASSIVE":
                                    {
                                        Command.LearnPassive(ClientSocket, ID);

                                        break;
                                    }
                                case "MESSAGE":
                                    {
                                        GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", Message);

                                        break;
                                    }
                            }
                        }
                    }
                }
            }
			// zone join commands
            if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureJCS"]))
            {
                foreach (String Command in Program.SQL.GetJoinCommands(ClientSocket.nCharNo)) { GlobalPacket.SendNormalMessageClient(ClientSocket, Command); }

                Program.SQL.DeleteJoinMessages(ClientSocket.nCharNo);
            }
			// zone join messages
            if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureJMS"]))
            {
                foreach (String Message in Program.SQL.GetJoinMessages(ClientSocket.nCharNo)) { GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", Message); }

                Program.SQL.DeleteJoinCommands(ClientSocket.nCharNo);
            }
        }

        [ZonePacketHandler(6, 9)]
        public static void HandleChangeMap(ZoneClient ClientSocket, Packet ServerPacket)
        {
            if (ClientSocket.TradeWaitAccept)
            {
                ClientSocket.TradeWaitAccept = false;

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

                GlobalPacket.SendCloseTrade(ClientSocket);
            }

            UInt16 MapID = ServerPacket.PacketReader.ReadUInt16();
            Int32 X = ServerPacket.PacketReader.ReadInt32();
            Int32 Y = ServerPacket.PacketReader.ReadInt32();

            ClientSocket.sMap = Convert.ToString(Program.MapInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToUInt16(ItemArray.ItemArray[0]) == MapID).FirstOrDefault().ItemArray[1]);
            ClientSocket.InstanceID = Program.SQL.GetsMapFromsID(ClientSocket.sID).Replace(ClientSocket.sMap, "");
            ClientSocket.X = X;
            ClientSocket.Y = Y;

            ClientSocket.IsReady = false;
            ClientSocket.SendPacketClient(ServerPacket);
        }

        [ZonePacketHandler(6, 10)]
        public static void HandleZoneIP(ZoneClient ClientSocket, Packet ServerPacket)
        {
            ClientSocket.IsReady = false;

            Byte[] Unk00 = ServerPacket.PacketReader.ReadBytes(10);
            String IPAddress = ServerPacket.ReadString(16);
            UInt16 Port = ServerPacket.PacketReader.ReadUInt16();
            Byte[] Unk01 = ServerPacket.PacketReader.ReadBytes(2);

            using (var ServerPacketRewrite = new Packet(6, 10))
            {
                ServerPacketRewrite.PacketWriter.Write(Unk00);
                ServerPacketRewrite.WriteString(Program.Auth.ConfigValues["ZoneTransferIP"], 16);
                ServerPacketRewrite.PacketWriter.Write(Port);
                ServerPacketRewrite.PacketWriter.Write(Unk01);

                ClientSocket.SendPacketClient(ServerPacketRewrite);
            }
        }
    }
}
