using System;
using System.Linq;
using System.Data;
using System.Threading;
using System.Collections.Generic;

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

using FilterZone.ZoneNetworking;

namespace FilterZone.ZoneHandlers
{
    internal class Zone12Handle
    {
        [ZonePacketHandler(12, 3)]
        public static void HandleBuyItem(ZoneClient ClientSocket, Packet ClientPacket)
        {
            if (ClientSocket.TradeWaitAccept)
            {
                ClientSocket.TradeWaitAccept = false;

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

                GlobalPacket.SendCloseTrade(ClientSocket);
            } // something something vendor protection
            else if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureAWVP"]) && ClientSocket.IsVending)
            {
                ClientSocket.Dispose();

                return;
            }

            UInt16 ItemID = UInt16.MaxValue;
            UInt32 Amount = 0;

            if (((ItemID = ClientPacket.PacketReader.ReadUInt16()) != UInt16.MaxValue) && ((Amount = ClientPacket.PacketReader.ReadUInt32()) != 0))
            {
                DataRow ItemRow = Program.ItemInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToUInt16(ItemArray.ItemArray[0]) == ItemID).FirstOrDefault();

                List<CurrencyItem> CurrencyItems = null;
                List<TokenItem> TokenItems = null;

                DataRow PortalNPCRow = null;

                if (Convert.ToInt32(ItemRow.ItemArray[30]) == 0) { GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "The item \"{0}\" cannot be bought from the NPC.", ItemRow[2]); }
                else if ((PortalNPCRow = Program.PortalNPC.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToUInt16(ItemArray.ItemArray[1]) == ItemID).FirstOrDefault()) != null)
                {
                    GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You have been teleported to {0}. X: {1}. Y: {2}.", Program.MapInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => ItemArray.ItemArray[1].ToString() == PortalNPCRow.ItemArray[2].ToString()).FirstOrDefault().ItemArray[2], PortalNPCRow.ItemArray[3], PortalNPCRow.ItemArray[4]);

                    Command.Linkto(ClientSocket, Convert.ToString(PortalNPCRow.ItemArray[2]), Convert.ToInt32(PortalNPCRow.ItemArray[3]), Convert.ToInt32(PortalNPCRow.ItemArray[4]));
                }
                else if ((CurrencyItems = Program.Currencies.CurrencyItemIDs.Where(CItemID => CItemID.ItemID == ItemID).ToList()).Count == 0 && (TokenItems = Program.Tokens.TokenItemIDs.Where(TItemID => TItemID.ItemID == ItemID).ToList()).Count == 0) { ClientSocket.SendPacketServer(ClientPacket); }
                else
                {
                    List<String> Messages = new List<String>();

                    Boolean HasEnough = true;

                    if (ClientSocket.BuyItemID != ItemID)
                    {
                        ClientSocket.BuyItemID = ItemID;
                        ClientSocket.BuyNeedsConfirm = true;
                    }
                    else
                    {
                        ClientSocket.BuyItemID = UInt32.MaxValue;
                        ClientSocket.BuyNeedsConfirm = false;
                    }

                    if (TokenItems != null && TokenItems.Count != 0)
                    {
                        foreach (TokenItem TI in TokenItems)
                        {
                            Token T = Program.Tokens.TokenInfo.Where(TokenID => TokenID.TokenID == TI.TokenID).FirstOrDefault();

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

                            Int64 TokenAmount = Program.SQL.GetAmountForCC(T.TableName, Type, Value);

                            if (TokenAmount == -1)
                            {
                                TokenAmount = 0;

                                HasEnough = false;
                            }
                            else if (TI.TokenCost * Amount > TokenAmount) { HasEnough = false; }

                            if (ClientSocket.BuyNeedsConfirm) { Messages.Add(String.Format("{0}: ({1}/{2}) [HaveEnough: {3}]", T.TokenName, TokenAmount, TI.TokenCost * Amount, HasEnough ? "Yes" : "No")); }
                            else { Messages.Add(String.Format("{0}: ({1}/{2}) [Need: {3}]", T.TokenName, TokenAmount, TI.TokenCost * Amount, (TI.TokenCost * Amount) - TokenAmount)); }
                        }

                        if (ClientSocket.BuyNeedsConfirm)
                        {
                            GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "Before purchasing this item please check you have enough space to accept it in your inventory.");
                            GlobalPacket.SendShoutMessageServer(ClientSocket, ".", "Here are you current token amounts for the tokens needed to buy this item:");

                            foreach (String Message in Messages) { GlobalPacket.SendShoutMessageServer(ClientSocket, ".", Message); }
                        }
                        else if (!HasEnough)
                        {
                            GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You do not have enough to buy this item you have:");

                            foreach (String Message in Messages) { GlobalPacket.SendShoutMessageServer(ClientSocket, ".", Message); }
                        }
                        else
                        {
                            Messages.Clear();

                            GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "Some of your tokens have been changed:");

                            foreach (TokenItem TI in TokenItems)
                            {
                                Token T = Program.Tokens.TokenInfo.Where(TokenID => TokenID.TokenID == TI.TokenID).FirstOrDefault();

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

                                Int64 TokenAmount = Program.SQL.GetAmountForCC(T.TableName, Type, Value);

                                Program.SQL.MinusAmountForCC(T.TableName, TI.TokenCost * Amount, Type, Value);

                                GlobalPacket.SendShoutMessageServer(ClientSocket, ".", "{0} has been taken from the token \"{1}\". You are left with {2}.", TI.TokenCost * Amount, T.TokenName, TokenAmount - (TI.TokenCost * Amount));
                            }

                            TokenItem TIMain = TokenItems.Where(IsMainHandle => IsMainHandle.IsMainHandle).FirstOrDefault();

                            if (TIMain.IsCharacterCreated)
                            {
                                String ItemIndex = Convert.ToString(Program.ItemInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToInt32(ItemArray.ItemArray[0]) == ItemID).FirstOrDefault().ItemArray[1]);

                                if (TIMain.HasUpgrade) { Command.Makeitem(ClientSocket, ItemIndex, true, TIMain.Upgrade); }
                                else { Command.Makeitem(ClientSocket, ItemIndex, Convert.ToByte(Amount)); }
                            }
                            else { ClientSocket.SendPacketServer(ClientPacket); }

                            String ItemName = Convert.ToString(Program.ItemInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToInt32(ItemArray.ItemArray[0]) == ItemID).FirstOrDefault().ItemArray[2]);

                            GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You have bought {0}x\"{1}\".", Amount, ItemName);
                        }
                    }
					// zone custom currency something
                    if (TokenItems == null && Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureCCB"]))
                    {
                        foreach (CurrencyItem CI in CurrencyItems)
                        {
                            Currency C = Program.Currencies.Currencies.Where(CurrencyID => CurrencyID.CurrencyID == CI.CurrencyID).FirstOrDefault();

                            if (C.IsDateSpecific)
                            {
                                String[] StartDateSplit = C.StartDate.Split('/');
                                String[] EndDateSplit = C.EndDate.Split('/');

                                DateTime StartDate = new DateTime(Convert.ToInt32(StartDateSplit[2]), Convert.ToInt32(StartDateSplit[1]), Convert.ToInt32(StartDateSplit[0]), 0, 0, 0);
                                DateTime EndDate = new DateTime(Convert.ToInt32(EndDateSplit[2]), Convert.ToInt32(EndDateSplit[1]), Convert.ToInt32(EndDateSplit[0]), 23, 59, 59);

                                if (StartDate > DateTime.Now)
                                {
                                    GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "The currency {0} is not useable yet. It can be used starting from: {1}, and ending on {2}.", C.CurrencyName, C.StartDate, C.EndDate);

                                    return;
                                }
                                else if (DateTime.Now > EndDate)
                                {
                                    GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "The currency {0} is no longer useable. It was useable from: {1} to {2}.", C.CurrencyName, C.StartDate, C.EndDate);

                                    return;
                                }
                            }

                            if (C.IsTimeSpecific)
                            {
                                String[] StartTimeSplit = C.StartTime.Split(':');
                                String[] EndTimeSplit = C.EndTime.Split(':');

                                DateTime StartTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, Convert.ToInt32(StartTimeSplit[0]), Convert.ToInt32(StartTimeSplit[1]), 0);
                                DateTime EndTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, Convert.ToInt32(EndTimeSplit[0]), Convert.ToInt32(EndTimeSplit[1]), 59);

                                if (StartTime > DateTime.Now)
                                {
                                    GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "The currency {0} is only useable between: {1} - {2}. Time now: {3}:{4}.", C.CurrencyName, C.StartTime, C.EndTime, DateTime.Now.Hour.ToString("00"), DateTime.Now.Minute.ToString("00"));

                                    return;
                                }
                                else if (DateTime.Now > EndTime)
                                {
                                    GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "The currency {0} is only useable between: {1} - {2}. Time now: {3}:{4}.", C.CurrencyName, C.StartTime, C.EndTime, DateTime.Now.Hour.ToString("00"), DateTime.Now.Minute.ToString("00"));

                                    return;
                                }
                            }

                            if (C.IsQuestSpecific && !Program.SQL.IsQuestComplete(ClientSocket.nCharNo, C.QuestID))
                            {
                                Int32 QuestNameID = Convert.ToInt32(Program.QuestData.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToInt32(ItemArray.ItemArray[0]) == C.QuestID).FirstOrDefault().ItemArray[1]);
                                String QuestName = Convert.ToString(Program.QuestDialog.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToInt32(ItemArray.ItemArray[0]) == QuestNameID).FirstOrDefault().ItemArray[1]);

                                GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You need to complete the quest \"{0}\" before you can use the currency {1}.", QuestName, C.CurrencyName);

                                return;
                            }

                            Int64 CurrencyCost = CI.CurrencyWorth * Amount;
                            String Type = C.IsCharacter ? "nCharNo" : "nUserNo";
                            Int32 Value = C.IsCharacter ? ClientSocket.nCharNo : ClientSocket.nUserNo;
                            Int64 CurrencyAmount = Program.SQL.GetAmountForCC(C.TableName, Type, Value);

                            if (C.HasDiscount) { CurrencyCost = Convert.ToInt32(Math.Round(Convert.ToDouble(CurrencyCost / C.Discount), 0)); }

                            Int64 CurrencyTake = CurrencyCost - CurrencyAmount;

                            if (0 > CurrencyTake) { CurrencyTake = 0; }

                            if (CurrencyAmount == -1)
                            {
                                CurrencyAmount = 0;

                                HasEnough = false;
                            }
                            else if (CurrencyCost > CurrencyAmount) { HasEnough = false; }

                            if (ClientSocket.BuyNeedsConfirm) { Messages.Add(String.Format("{0}: ({1}/{2}) [HaveEnough: {3}]", C.CurrencyName, CurrencyAmount, CurrencyCost, HasEnough ? "Yes" : "No")); }
                            else { Messages.Add(String.Format("{0}: ({1}/{2}) [Need: {3}]", C.CurrencyName, CurrencyAmount, CurrencyCost, CurrencyTake)); }
                        }

                        if (ClientSocket.BuyNeedsConfirm)
                        {
                            GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "Before purchasing this item please check you have enough space to accept it in your inventory.");
                            GlobalPacket.SendShoutMessageServer(ClientSocket, ".", "Here are you current currency amounts for the currencies needed to buy this item:");

                            foreach (String Message in Messages) { GlobalPacket.SendShoutMessageServer(ClientSocket, ".", Message); }
                        }
                        else if (!HasEnough)
                        {
                            GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You do not have enough to buy this item you have:");

                            foreach (String Message in Messages) { GlobalPacket.SendShoutMessageServer(ClientSocket, ".", Message); }
                        }
                        else
                        {
                            Messages.Clear();

                            GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "Some of your currencies have been changed:");

                            foreach (CurrencyItem CI in CurrencyItems)
                            {
                                Currency C = Program.Currencies.Currencies.Where(CurrencyID => CurrencyID.CurrencyID == CI.CurrencyID).FirstOrDefault();

                                Int64 CurrencyCost = CI.CurrencyWorth * Amount;
                                String Type = C.IsCharacter ? "nCharNo" : "nUserNo";
                                Int32 Value = C.IsCharacter ? ClientSocket.nCharNo : ClientSocket.nUserNo;
                                Int64 CurrencyAmount = Program.SQL.GetAmountForCC(C.TableName, Type, Value);

                                if (C.HasDiscount) { CurrencyCost = Convert.ToInt32(Math.Round(Convert.ToDouble(CurrencyCost / C.Discount), 0)); }

                                Program.SQL.MinusAmountForCC(C.TableName, CurrencyCost, Type, Value);

                                GlobalPacket.SendShoutMessageServer(ClientSocket, ".", "{0} has been taken from the currency \"{1}\". You are left with {2}.", CurrencyCost, C.CurrencyName, CurrencyAmount - CurrencyCost);
                            }

                            CurrencyItem CIMain = CurrencyItems.Where(IsMainHandle => IsMainHandle.IsMainHandle).FirstOrDefault();

                            if (CIMain.IsMob)
                            {
                                String MobName = Convert.ToString(Program.MobInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => ItemArray.ItemArray[1].ToString() == CIMain.MobIndex).FirstOrDefault().ItemArray[2]);

                                for (UInt32 Counter = 0; Counter < CIMain.MobAmount * Amount; Counter++) { Command.Mobbreed(ClientSocket, CIMain.MobIndex, 1, 0, false, 1); }

                                GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "{0}x\"{1}\" have been spawned at your current location.", Amount, MobName);
                            }
                            else if (CIMain.IsAbstate)
                            {
                                String AbstateName = Convert.ToString(Program.AbStateView.Table.Rows.Cast<DataRow>().Where(ItemArray => ItemArray.ItemArray[0].ToString() == CIMain.AbstateIndex).FirstOrDefault().ItemArray[4]);

                                Command.SetAbstate(ClientSocket, CIMain.AbstateIndex, CIMain.AbstateDuration, CIMain.AbstateEffect);

                                GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You have bought {0} seconds of \"{1}\".", CIMain.AbstateDuration / 1000, AbstateName);
                            }
                            else if (CIMain.IsTrigger)
                            {
                                Boolean Refund = false;

                                switch (CIMain.TriggerID)
                                {
                                    case 0:
                                        {
                                            if (Program.SQL.HastUnlimitedRoars(ClientSocket.nCharNo))
                                            {
                                                Refund = true;

                                                GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You already have unlimited raors. Your currencies have been refunded");
                                            }
                                            else
                                            {
                                                Program.SQL.InserttUnlimitedRoars(ClientSocket.nCharNo);

                                                GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You have bought unlimited roars.");
                                            }

                                            break;
                                        }
                                    case 1:
                                        {
                                            Program.SQL.AddtStatRerollFornCharNo(ClientSocket.nCharNo, Amount);

                                            GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You have bought {0}x\"Stat reroll\".", Amount);

                                            break;
                                        }
                                }

                                if (Refund)
                                {
                                    foreach (CurrencyItem CI in CurrencyItems)
                                    {
                                        Currency C = Program.Currencies.Currencies.Where(CurrencyID => CurrencyID.CurrencyID == CI.CurrencyID).FirstOrDefault();

                                        Int64 CurrencyCost = CI.CurrencyWorth * Amount;
                                        String Type = C.IsCharacter ? "nCharNo" : "nUserNo";
                                        Int32 Value = C.IsCharacter ? ClientSocket.nCharNo : ClientSocket.nUserNo;
                                        Int64 CurrencyAmount = Program.SQL.GetAmountForCC(C.TableName, Type, Value);

                                        if (C.HasDiscount) { CurrencyCost = Convert.ToInt32(Math.Round(Convert.ToDouble(CurrencyCost / C.Discount), 0)); }

                                        Program.SQL.AddAmountForCC(C.TableName, CurrencyCost, Type, Value);
                                    }
                                }
                            }
                            else
                            {
                                if (CIMain.IsCharacterCreated)
                                {
                                    String ItemIndex = Convert.ToString(Program.ItemInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToInt32(ItemArray.ItemArray[0]) == ItemID).FirstOrDefault().ItemArray[1]);

                                    if (CIMain.HasUpgrade) { Command.Makeitem(ClientSocket, ItemIndex, CIMain.Upgrade, Convert.ToByte(Amount)); }
                                    else if (Amount == 1) { Command.Makeitem(ClientSocket, ItemIndex); }
                                    else { Command.Makeitem(ClientSocket, ItemIndex, Convert.ToByte(Amount)); }
                                }
                                else { ClientSocket.SendPacketServer(ClientPacket); }

                                String ItemName = Convert.ToString(Program.ItemInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToInt32(ItemArray.ItemArray[0]) == ItemID).FirstOrDefault().ItemArray[2]);

                                GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You have bought {0}x\"{1}\".", Amount, ItemName);
                            }
                        }
                    }
                    else if (TokenItems == null) { ClientSocket.SendPacketServer(ClientPacket); }
                }
            }
        }

        [ZonePacketHandler(12, 6)]
        public static void HandleSellItem(ZoneClient ClientSocket, Packet ClientPacket)
        {
            if (ClientSocket.TradeWaitAccept)
            {
                ClientSocket.TradeWaitAccept = false;

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

                GlobalPacket.SendCloseTrade(ClientSocket);
            } // zone something something vendor protection
            else if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureAWVP"]) && ClientSocket.IsVending)
            {
                ClientSocket.Dispose();

                return;
            }

            Int16 SlotID = -1;
            Byte Amount;

            if (ClientSocket.SellDateTime > DateTime.Now) { GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "Please wait 1 second between each sale to the NPC."); }
            else if (((SlotID = ClientPacket.PacketReader.ReadByte()) != -1) && ((Amount = ClientPacket.PacketReader.ReadByte()) != 0))
            {
                if (Program.SQL.HasItemInSlot(ClientSocket.nCharNo, SlotID))
                {
                    ClientSocket.SellDateTime = DateTime.Now.AddSeconds(1);

                    UInt32 ItemID = Program.SQL.GetnItemIDFromnOwnerAndnStorage(ClientSocket.nCharNo, Convert.ToByte(SlotID));
                    Int64 ItemKey = Program.SQL.GetnItemKeyFromnOwnerAndnStorage(ClientSocket.nCharNo, SlotID);

                    DataRow ItemRow = Program.ItemInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToInt32(ItemArray.ItemArray[0]) == ItemID).FirstOrDefault();

                    if (ItemKey == -1) { ClientSocket.Dispose(); }
                    else if (Convert.ToBoolean(ItemRow.ItemArray[52]) || Convert.ToInt32(ItemRow.ItemArray[31]) == 0) { GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "The item \"{0}\" cannot be sold to the NPC.", ItemRow[2]); }
                    else
                    { // zone sale protection
                        if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureSP"]))
                        {
                            Int16 ItemAmount = Program.SQL.GetAmountForItem(ItemKey);

                            if (!ClientSocket.ItemAmounts.ContainsKey(ItemKey)) { ClientSocket.ItemAmounts.Add(ItemKey, ItemAmount); }

                            Int16 DictionaryAmount = ClientSocket.ItemAmounts[ItemKey];

                            if (DictionaryAmount <= 0 || Amount > DictionaryAmount)
                            {
                                Program.SQL.DeleteItem(ItemKey);

                                ClientSocket.Dispose();

                                return;
                            }
                            else
                            {
                                ClientSocket.SendPacketServer(ClientPacket);
                                ClientSocket.ItemAmounts[ItemKey] = (Int16)(ClientSocket.ItemAmounts[ItemKey] - Amount);

                                Thread.Sleep(50);

                                if (ItemAmount == 1 || ClientSocket.ItemAmounts[ItemKey] <= 0) { Program.SQL.DeleteItem(ItemKey); }
                                else { Program.SQL.SetAmountForItem(ItemKey, Convert.ToByte(ClientSocket.ItemAmounts[ItemKey])); }
                            }
                        }
                        else { ClientSocket.SendPacketServer(ClientPacket); }
						// zone tax system
                        if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureTS"]))
                        {
                            Int64 Tax = Convert.ToInt64(Math.Round(Convert.ToDouble(((Convert.ToInt64(ItemRow.ItemArray[31]) * Amount) / 100) * 5), 0));

                            if (Tax != 0)
                            {
                                Program.SQL.SetnMoneyFortTaxLottery(Tax);

                                GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "{0} has been added to the tax lottery. Due to you selling \"{1}\".", Money.ConvertMoney(Tax), ItemRow.ItemArray[2]);
                            }
                        }

                        List<TokenItem> TokenItems;

                        if ((TokenItems = Program.Tokens.TokenItemIDs.Where(TItemID => TItemID.ItemID == ItemID).ToList()).Count != 0)
                        {
                            foreach (TokenItem TI in TokenItems)
                            {
                                if (TI.TokenWorth > 0)
                                {
                                    Token T = Program.Tokens.TokenInfo.Where(TokenID => TokenID.TokenID == TI.TokenID).FirstOrDefault();

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

                                    Program.SQL.AddAmountForCC(T.TableName, TI.TokenWorth * Amount, Type, Value);

                                    GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You obtained {0}x\"{1}\".", TI.TokenWorth * Amount, T.TokenName);
                                }
                            }
                        }
						// zone custom currency (sale)?
                        if (TokenItems.Count == 0 && Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureCCS"]))
                        {
                            List<CurrencyItem> CurrencyItems;

                            if ((CurrencyItems = Program.Currencies.CurrencyItemIDs.Where(CItemID => CItemID.ItemID == ItemID).Where(CIsCoin => CIsCoin.IsCoin == true).ToList()).Count != 0)
                            {
                                foreach (CurrencyItem CI in CurrencyItems.Where(IsAutoAdd => !IsAutoAdd.IsAutoAdd).ToList())
                                {
                                    Currency C = Program.Currencies.Currencies.Where(CurrencyID => CurrencyID.CurrencyID == CI.CurrencyID).FirstOrDefault();

                                    Int64 CurrencyWorth = CI.CurrencyWorth * Amount;
                                    String Type = C.IsCharacter ? "nCharNo" : "nUserNo";
                                    Int32 Value = C.IsCharacter ? ClientSocket.nCharNo : ClientSocket.nUserNo;

                                    if (C.HasMaximum)
                                    {
                                        Int32 CurrencyObtained = Program.SQL.GetObtainedForCC(C.TableName, Type, Value);

                                        if (CurrencyObtained == -1)
                                        {
                                            Program.SQL.AddObtainedForCC(C.TableName, 0, Type, Value);

                                            CurrencyObtained = 0;
                                        }

                                        if ((CurrencyObtained + CurrencyWorth) > C.Maximum)
                                        {
                                            Int32 AddObtained = Convert.ToInt32(C.Maximum - CurrencyObtained);

                                            Program.SQL.AddAmountForCC(C.TableName, AddObtained, Type, Value);
                                            Program.SQL.AddObtainedForCC(C.TableName, Convert.ToInt16(AddObtained), Type, Value);

                                            String TypeName = C.IsCharacter ? "character" : "account";

                                            GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You cannot obtain anymore of \"{0}\" on this {1}, as you have obtained the maximum, which is {2}.", C.CurrencyName, TypeName, C.Maximum);
                                        }
                                        else
                                        {
                                            Int32 AddObtained = Convert.ToInt32(CurrencyObtained + CurrencyWorth);

                                            Program.SQL.AddAmountForCC(C.TableName, AddObtained, Type, Value);
                                            Program.SQL.AddObtainedForCC(C.TableName, Convert.ToInt16(AddObtained), Type, Value);

                                            GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You obtained {0}x\"{1}\".", CurrencyWorth, C.CurrencyName);
                                        }
                                    }
                                    else
                                    {
                                        Program.SQL.AddAmountForCC(C.TableName, CurrencyWorth, Type, Value);

                                        GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You obtained {0}x\"{1}\".", CurrencyWorth, C.CurrencyName);
                                    }
                                }
                            }
                        }
                    }
                }
                else { ClientSocket.Dispose(); }
            }
        }

        [ZonePacketHandler(12, 7)]
        public static void HandleDropItem(ZoneClient ClientSocket, Packet ClientPacket)
        {
            if (!Program.SQL.HasPermission(ClientSocket.nCharNo, "CanDrop")) { GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "Sorry \"{0}\", you are not allowed to drop items.", ClientSocket.sID); }
            else if (Program.AntiDropMapIndexs.Keys.Contains(ClientSocket.sMap)) { GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You cannot drop items in \"{0}\".", Program.AntiDropMapIndexs[ClientSocket.sMap]); }
            else
            { // zone custom currency drop intervention
                if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureCCDI"]))
                {
                    Int16 SlotID = -1;

                    if ((SlotID = ClientPacket.PacketReader.ReadByte()) != -1)
                    {
                        UInt32 ItemID = Program.SQL.GetnItemIDFromnOwnerAndnStorage(ClientSocket.nCharNo, Convert.ToByte(SlotID));

                        List<CurrencyItem> CurrencyItems;

                        if ((CurrencyItems = Program.Currencies.CurrencyItemIDs.Where(CItemID => CItemID.ItemID == ItemID).Where(CIsMainhandle => CIsMainhandle.IsMainHandle == true).Where(CIsCoin => CIsCoin.IsCoin == true).ToList()).Count == 0) { ClientSocket.SendPacketServer(ClientPacket); }
                        else if (CurrencyItems[0].IsAutoAdd)
                        {
                            String ItemName = Convert.ToString(Program.ItemInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToInt32(ItemArray.ItemArray[0]) == ItemID).FirstOrDefault().ItemArray[2]);

                            GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You cannot drop \"{0}\" as this is a coin that adds currency to you on pick up. Please sell it to an NPC.", ItemName);
                        }
                        else { ClientSocket.SendPacketServer(ClientPacket); }
                    }
                }
                else { ClientSocket.SendPacketServer(ClientPacket); }
            }
        }

        [ZonePacketHandler(12, 9)]
        public static void HandlePickupItem(ZoneClient ClientSocket, Packet ClientPacket)
        {
            if (!Program.SQL.HasPermission(ClientSocket.nCharNo, "CanPickUp")) { GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "Sorry \"{0}\", you are not allowed to pickup items.", ClientSocket.sID); }
            else
            {
                ClientSocket.SendPacketServer(ClientPacket);
				// zone pick up currency (protection)?
                if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeaturePUCP"]))
                {
                    UInt16 MapObjectID;

                    if ((MapObjectID = ClientPacket.PacketReader.ReadUInt16()) != UInt16.MaxValue)
                    {
                        MapObject MO;

                        if ((MO = ClientSocket.MapObjects.ToArray().Where(MOID => MOID.MapObjectID == MapObjectID).FirstOrDefault()) != null && MO.ItemID == Convert.ToUInt16(Program.Auth.ConfigValues["ZoneCenItemID"]))
                        {
                            Random RandomGenerator = new Random();

                            Int32 nMinimum;
                            Int32 nMaximum;

                            Program.SQL.GetnMinimumAndnMaximum(out nMinimum, out nMaximum);

                            Int64 AddMoney = RandomGenerator.Next(nMinimum, nMaximum);

                            Program.SQL.PutMoneyInStorage(ClientSocket.sID, AddMoney);

                            if (Program.SQL.ShowCenMessage()) { GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "{0} has been added to your storage for picking up {1}!", Money.ConvertMoney(AddMoney), Program.ItemInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToUInt16(ItemArray.ItemArray[0]) == MO.ItemID).FirstOrDefault().ItemArray[2]); }
                        }

                        ClientSocket.MapObjects.RemoveAll(MOID => MOID.MapObjectID == MapObjectID);
                    }
                }
            }
        }

        [ZonePacketHandler(12, 21)]
        public static void HandleUseItem(ZoneClient ClientSocket, Packet ClientPacket)
        { // zone use item (trade protection)?
            if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureUITP"]))
            {
                Int16 SlotID = -1;

                if ((SlotID = ClientPacket.PacketReader.ReadByte()) != -1)
                {
                    if (ClientSocket.TradeWaitAccept)
                    {
                        ClientSocket.TradeWaitAccept = false;

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

                        GlobalPacket.SendCloseTrade(ClientSocket);
                    }

                    UInt16 ItemID = UInt16.MaxValue;
                    Int64 ItemKey = Int64.MaxValue;

                    if ((ItemID = Program.SQL.GetnItemIDFromnOwnerAndnStorage(ClientSocket.nCharNo, Convert.ToByte(SlotID))) != UInt16.MaxValue && (ItemKey = Program.SQL.GetnItemKeyFromnOwnerAndnStorage(ClientSocket.nCharNo, SlotID)) != Int64.MaxValue)
                    {
                        ClientSocket.SendPacketServer(ClientPacket);

                        foreach (DataRow Row in Program.VaultReplacer.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToUInt16(ItemArray.ItemArray[0]) == ItemID))
                        {
                            Random RandomGenerator = new Random();

                            Byte RatioOutput = Convert.ToByte(RandomGenerator.Next(0, Convert.ToByte(Row[3])));

                            if (RatioOutput < Convert.ToByte(Row[2])) { Command.Makeitem(ClientSocket, Convert.ToString(Program.ItemInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToUInt16(ItemArray.ItemArray[0]) == Convert.ToUInt16(Row.ItemArray[1])).FirstOrDefault().ItemArray[1])); }
                        }

                        foreach (DataRow Row in Program.ItemUseEffect.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToUInt16(ItemArray.ItemArray[0]) == ItemID))
                        {
                            Random RandomGenerator = new Random();

                            Byte RatioOutput = Convert.ToByte(RandomGenerator.Next(0, Convert.ToByte(Row[6])));

                            if (RatioOutput < Convert.ToByte(Row[5]))
                            {
                                switch (Convert.ToString(Row.ItemArray[1]))
                                {
                                    case "LEVELUP":
                                        {
                                            Byte nLevel = Program.SQL.GetnLevelFromsID(ClientSocket.sID);

                                            if (nLevel >= Convert.ToByte(Row.ItemArray[3])) { GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "The item you tried to use has a maximum of level {0}, you are level {1}.", Row.ItemArray[3], nLevel); }
                                            else if (nLevel + Convert.ToByte(Row.ItemArray[2]) > Convert.ToByte(Row.ItemArray[3]))
                                            {
                                                Command.Levelup(ClientSocket, Convert.ToByte(nLevel - Convert.ToByte(Row.ItemArray[3])));

                                                GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You have been leveled up by {0} levels, but the item is suppose to level {1}. This is because of the item having a cap of {2}.", nLevel - Convert.ToByte(Row.ItemArray[3]), Row.ItemArray[2], Row.ItemArray[3]);
                                            }
                                            else
                                            {
                                                Command.Levelup(ClientSocket, Convert.ToByte(Row.ItemArray[2]));

                                                GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You have been leveled up by {0} levels.", Row.ItemArray[2]);
                                            }

                                            break;
                                        }
                                    case "TELEPORT":
                                        {
                                            String MapName = Convert.ToString(Program.MapInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => ItemArray.ItemArray[1].ToString() == Convert.ToString(Row.ItemArray[2])).FirstOrDefault().ItemArray[2]);

                                            GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You have been teleported to {0}. X: {1}. Y: {2}.", MapName, Row.ItemArray[3], Row.ItemArray[4]);

                                            Command.Linkto(ClientSocket, Convert.ToString(Row.ItemArray[2]), Convert.ToInt32(Row.ItemArray[3]), Convert.ToInt32(Row.ItemArray[4]));

                                            break;
                                        }
                                    case "MOB":
                                        {
                                            for (Int32 Counter = 0; Counter < Convert.ToInt32(Row.ItemArray[3]); Counter++) { Command.Mobbreed(ClientSocket, Convert.ToString(Row.ItemArray[2]), 1, 0, false, 1); }

                                            String MobName = Convert.ToString(Program.MobInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => ItemArray.ItemArray[1].ToString() == Convert.ToString(Row.ItemArray[2])).FirstOrDefault().ItemArray[2]);

                                            GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "{0}x\"{1}\" have been spawned at your location.", Row.ItemArray[3], MobName);

                                            break;
                                        }
                                    case "ITEM":
                                        {
                                            String ItemName = Convert.ToString(Program.ItemInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToString(ItemArray.ItemArray[1]) == Convert.ToString(Row.ItemArray[2])).FirstOrDefault().ItemArray[2]);

                                            if (Convert.ToByte(Row.ItemArray[3]) == 0)
                                            {
                                                Command.Makeitem(ClientSocket, Convert.ToString(Row.ItemArray[2]));

                                                GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You have been given \"{0}\".", ItemName);
                                            }
                                            else if (Convert.ToByte(Row.ItemArray[3]) == 1)
                                            {
                                                Command.Makeitem(ClientSocket, Convert.ToString(Row.ItemArray[2]), Convert.ToByte(Row.ItemArray[4]));

                                                GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You have been given {0}x\"{1}\".", Row.ItemArray[4], ItemName);
                                            }
                                            else
                                            {
                                                Command.Makeitem(ClientSocket, Convert.ToString(Row.ItemArray[2]), true, Convert.ToByte(Row.ItemArray[4]));

                                                GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You have been given \"{0}\" [+{1}].", ItemName, Row.ItemArray[4]);
                                            }

                                            break;
                                        }
                                    case "CURRENCY":
                                        {
                                            Currency C = Program.Currencies.Currencies.Where(CurrencyID => CurrencyID.CurrencyID == Convert.ToByte(Row.ItemArray[2])).FirstOrDefault();

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

                                            Program.SQL.AddAmountForCC(C.TableName, Convert.ToInt32(Row.ItemArray[3]), Type, Value);

                                            GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You obtained {0}x\"{1}\".", Row.ItemArray[3], C.CurrencyName);

                                            break;
                                        }
                                    case "MONEY":
                                        {
                                            Program.SQL.PutMoneyInStorage(ClientSocket.nUserNo, Convert.ToInt64(Row.ItemArray[2]));

                                            GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "You have been given \"{0}\" to your storage.", Money.ConvertMoney(Convert.ToInt64(Row.ItemArray[2])));

                                            break;
                                        }
                                }
                            }
                        }

                        if (Program.VaultReplacer.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToUInt16(ItemArray.ItemArray[0]) == ItemID).Count() != 0 || Program.ItemUseEffect.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToUInt16(ItemArray.ItemArray[0]) == ItemID).Count() != 0)
                        {
                            Int16 ItemAmount = Program.SQL.GetAmountForItem(ItemKey);

                            if (ItemAmount == 1) { Program.SQL.DeleteItem(ItemKey); }
                            else { Program.SQL.SetAmountForItem(ItemKey, Convert.ToByte(ItemAmount - 1)); }
                        }
                    }
                }
            }
            else { ClientSocket.SendPacketServer(ClientPacket); }
        }

        [ZonePacketHandler(12, 32)]
        public static void HandlePremiumInventory(ZoneClient ClientSocket, Packet ClientPacket)
        { // zone premium inventory spam protection
            if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeaturePISP"]))
            {
                if (ClientSocket.PremiumDateTime > DateTime.Now)
                {
                    TimeSpan PremiumSpan = ClientSocket.PremiumDateTime - DateTime.Now;

                    if (PremiumSpan.TotalSeconds > 60)
                    {
                        ClientSocket.Dispose();

                        return;
                    }

                    ClientSocket.PremiumDateTime = ClientSocket.PremiumDateTime.AddSeconds(5);

                    GlobalPacket.SendShoutMessageServer(ClientSocket, "Server", "Please wait 5 seconds before pressing the premium inventory button agian, or you will banned!");
                }
                else
                {
                    ClientSocket.PremiumDateTime = DateTime.Now.AddSeconds(5);

                    ClientSocket.SendPacketServer(ClientPacket);
                }
            }
            else { ClientSocket.SendPacketServer(ClientPacket); }
        }
    }
}
