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

namespace FilterAPI
{
    public class Item
    {
        private Database SQL;
        private List<Int64> ItemKeys = new List<Int64>();

        public Item(Database SQLI) { SQL = SQLI; }

        public Int64 CreateItem(Int32 nCharNo, Int32 nItemID, Byte nStorageType)
        {
            Int64 nItemKey = CreateItemKey();
            Byte nStorage = AvailablenStorage(nCharNo, nStorageType);

            InsertItem(nItemKey, nStorageType, nCharNo, nStorage, nItemID, 0, DateTime.Now);

            return nItemKey;
        }

        private Int64 CreateItemKey()
        {
            Int64 ItemKey = DateTime.Now.Ticks / 10;
            
            if (!ItemKeyTaken(ItemKey) && !ItemKeys.Contains(ItemKey)) { ItemKeys.Add(ItemKey); }
            else
            {
                Thread.Sleep(1);

                ItemKey = CreateItemKey();
            }

            return ItemKey;
        }

        private Boolean ItemKeyTaken(Int64 nItemKey)
        {
            if (SQL.Connection.State != ConnectionState.Open) { SQL.Connection.Open(); }

            using (SqlCommand Command = SQL.Connection.CreateCommand())
            {
                Command.CommandText = String.Format("SELECT TOP 1 nItemkey FROM {0}..tItem WHERE nItemKey = '{1}'", SQL.CharacterDB, nItemKey);

                if (Convert.ToInt64(Command.ExecuteScalar()) != 0) { return true; }
            }

            return false;
        }

        private Byte AvailablenStorage(Int32 nCharNo, Byte nStorageType)
        {
            if (SQL.Connection.State != ConnectionState.Open) { SQL.Connection.Open(); }

            List<Byte> TakennStorage = new List<Byte>();

            using (SqlCommand Command = SQL.Connection.CreateCommand())
            {
                Command.CommandText = String.Format("SELECT nStorage FROM {0}..tItem WHERE nOwner = '{1}' AND nStorageType = '{2}'", SQL.CharacterDB, nCharNo, nStorageType);

                using (SqlDataReader Reader = Command.ExecuteReader())
                {
                    while (Reader.Read()) { TakennStorage.Add(Convert.ToByte(Reader["nStorage"])); }

                    for (Byte Counter = 0; Counter < 255; Counter++)
                    {
                        if (!TakennStorage.Contains(Counter)) { return Counter; }
                    }
                }
            }

            return 255;
        }

        private void InsertItem(Int64 nItemKey, Byte nStorageType, Int32 nOwner, Byte nStorage, Int32 nItemID, Byte nFlags, DateTime dDate)
        {
            if (SQL.Connection.State != ConnectionState.Open) { SQL.Connection.Open(); }

            using (SqlCommand Command = SQL.Connection.CreateCommand())
            {
                Command.CommandText = String.Format("INSERT INTO {0}..tItem (nItemKey, nStorageType, nOwner, nStorage, nItemID, nFlags, dDate) VALUES ('{1}', '{2}', '{3}', '{4}', '{5}', '{6}', '{7}')", SQL.CharacterDB, nItemKey, nStorageType, nOwner, nStorage, nItemID, nFlags, DateTime.Now);
                Command.ExecuteNonQuery();
            }
        }

        public void InsertMobLicense(Int64 nItemKey, UInt16 nMobID, Byte nGrade, Int32 nKillCount)
        {
            if (SQL.Connection.State != ConnectionState.Open) { SQL.Connection.Open(); }

            using (SqlCommand Command = SQL.Connection.CreateCommand())
            {
                Command.CommandText = String.Format("INSERT INTO {0}..tItemMobList (nItemKey, nMobID, nGrade, nKillCount) VALUES ('{1}', '{2}', '{3}', '{4}')", SQL.CharacterDB, nItemKey, nMobID, nGrade, nKillCount);
                Command.ExecuteNonQuery();
            }
        }

        public void InsertOptions(Int64 nItemKey, ItemOptions Options)
        {
            switch (Options.Type)
            {
                case 0:
                case 12:
                case 14:
                case 19:
                case 20:
                case 22:
                case 25:
                    {
                        InsertOption(nItemKey, 1, Options.Amount);

                        break;
                    }
                case 3:
                    {
                        InsertOption(nItemKey, 300, Options.Amount);

                        break;
                    }
                case 4:
                    {
                        InsertOption(nItemKey, 400, 11);

                        InsertStats(nItemKey, Options, 401, 402);

                        InsertOption(nItemKey, 417, 0);
                        InsertOption(nItemKey, 418, Options.Upgrade);

                        for (Int16 Counter = 419; Counter < 426; Counter++) { InsertOption(nItemKey, Counter, 0); }

                        break;
                    }
                case 5:
                    {
                        InsertOption(nItemKey, 500, Options.Upgrade);
                        InsertOption(nItemKey, 501, 0);
                        InsertOption(nItemKey, 502, 0);
                        InsertOption(nItemKey, 503, 11);

                        InsertStats(nItemKey, Options, 504, 505);

                        InsertOption(nItemKey, 520, 65535);
                        InsertOption(nItemKey, 521, 0);

                        break;
                    }
                case 7:
                    {
                        InsertOption(nItemKey, 700, Options.Upgrade);
                        InsertOption(nItemKey, 701, 0);
                        InsertOption(nItemKey, 702, 0);
                        InsertOption(nItemKey, 703, 11);

                        InsertStats(nItemKey, Options, 704, 705);

                        InsertOption(nItemKey, 720, 0);

                        break;
                    }
                case 8:
                    {
                        InsertOption(nItemKey, 800, Options.Upgrade);

                        for (Int16 Counter = 801; Counter < 803; Counter++) { InsertOption(nItemKey, Counter, 0); }

                        InsertOption(nItemKey, 803, 5);

                        InsertStats(nItemKey, Options, 804, 805);

                        InsertOption(nItemKey, 820, 0);

                        break;
                    }
                case 10:
                    {
                        InsertOption(nItemKey, 1001, Options.RunOut);

                        break;
                    }
                case 18:
                    {
                        InsertOption(nItemKey, 1501, Options.RunOut);

                        break;
                    }
                case 24:
                    {
                        InsertOption(nItemKey, 4, Options.LeftToUse);

                        break;
                    }
                case 26:
                    {
                        InsertOption(nItemKey, 1800, Options.Durability);

                        break;
                    }
                case 27:
                    {
                        InsertOption(nItemKey, 1900, Options.RunOut);

                        break;
                    }
            }
        }

        private void InsertStats(Int64 nItemKey, ItemOptions Options, Int16 StatType, Int16 StatValue)
        {
            for (Int32 Counter = 0; Counter < 5; Counter++)
            {
                if (Options.STR != -1)
                {
                    InsertOption(nItemKey, StatType, 0);
                    InsertOption(nItemKey, StatValue, Options.STR);

                    Options.STR = -1;

                    StatType = Convert.ToInt16(StatType + 2);
                    StatValue = Convert.ToInt16(StatValue + 2);
                }
                else if (Options.END != -1)
                {
                    InsertOption(nItemKey, StatType, 1);
                    InsertOption(nItemKey, StatValue, Options.END);

                    Options.END = -1;

                    StatType = Convert.ToInt16(StatType + 2);
                    StatValue = Convert.ToInt16(StatValue + 2);
                }
                else if (Options.DEX != -1)
                {
                    InsertOption(nItemKey, StatType, 2);
                    InsertOption(nItemKey, StatValue, Options.DEX);

                    Options.DEX = -1;

                    StatType = Convert.ToInt16(StatType + 2);
                    StatValue = Convert.ToInt16(StatValue + 2);
                }
                else if (Options.INT != -1)
                {
                    InsertOption(nItemKey, StatType, 3);
                    InsertOption(nItemKey, StatValue, Options.INT);

                    Options.INT = -1;

                    StatType = Convert.ToInt16(StatType + 2);
                    StatValue = Convert.ToInt16(StatValue + 2);
                }
                else if (Options.SPR != -1)
                {
                    InsertOption(nItemKey, StatType, 4);
                    InsertOption(nItemKey, StatValue, Options.SPR);

                    Options.SPR = -1;

                    StatType = Convert.ToInt16(StatType + 2);
                    StatValue = Convert.ToInt16(StatValue + 2);
                }
            }
        }

        private void InsertOption(Int64 nItemKey, Int16 nOptionType, Int64 nOptionData)
        {
            if (SQL.Connection.State != ConnectionState.Open) { SQL.Connection.Open(); }

            using (SqlCommand Command = SQL.Connection.CreateCommand())
            {
                Command.CommandText = String.Format("INSERT INTO {0}..tItemOptions (nItemKey, nOptionType, nOptionData) VALUES ('{1}', '{2}', '{3}')", SQL.CharacterDB, nItemKey, nOptionType, nOptionData);
                Command.ExecuteNonQuery();
            }
        }

        public void InsertItemTitle(Int64 nItemKey, Byte nTitleType, String sTitle, Int32 nTitleCharNo)
        {
            if (SQL.Connection.State != ConnectionState.Open) { SQL.Connection.Open(); }

            using (SqlCommand Command = SQL.Connection.CreateCommand())
            {
                Command.CommandText = String.Format("INSERT INTO {0}..tItemTitle (nItemKey, nTitleType, sTitle, nTitleCharNo) VALUES ('{1}', '{2}', '{3}', '{4}')", SQL.CharacterDB, nItemKey, nTitleType, sTitle, nTitleCharNo);
                Command.ExecuteNonQuery();
            }
        }
    }
}
