using System;
using System.Text;
using System.Linq;
using System.Data;
using System.Reflection;
using System.ServiceProcess;
using System.Collections.Generic;

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

using FilterTimers.LocalHandlers;
using FilterTimers.LocalNetworking;

using CS;
using SHN;
using System.Threading;

namespace FilterTimers
{
    internal class Program
    {
        public static String ServiceName = "Timers";

        public static Authentication Auth;
        public static Database SQL;
        public static CurrencyLoader Currencies;

        public static SHNFile AbStateView;
        public static SHNFile ActiveSkill;
        public static SHNFile ItemInfo;
        public static SHNFile PassiveSkill;

        public static SHNFile ItemAbstateGroups;
        public static SHNFile ItemAbstates;
        public static SHNFile WinnableAbstates;
        public static SHNFile Rebirth;
        public static SHNFile AntiAutoSkillLearn;
        public static SHNFile AntiAutoPassiveLearn;
        public static SHNFile PartyAbstates;

        public static Dictionary<Byte, List<Object[]>> ClassSkills = new Dictionary<Byte, List<Object[]>>();
        public static Dictionary<Byte, List<Object[]>> ClassPassives = new Dictionary<Byte, List<Object[]>>();

        public static LocalClient LocalClient;
        public static LocalHandlerLoader LocalHandlers;

        private static void Main()
        {
			if (Environment.UserInteractive)
			{
				Service s = new Service();
				s.Init(); // Init() is pretty much any code you would have in OnStart().
				while (true) { Thread.Sleep(1); }
			}
			else
			{
				ServiceBase[] ServicesToRun = new ServiceBase[] { new Service() };
				ServiceBase.Run(ServicesToRun);
			}
		}

        public static void SendConsoleText(ConsoleColor WriteColor, String Text, params Object[] Args)
        {
            String FormattedText = String.Format(Text, Args);

            using (var ClientPacket = new Packet(2, 3))
            {
                ClientPacket.PacketWriter.Write(ConsoleColorConverter.ConsoleColorToID(WriteColor));
                ClientPacket.PacketWriter.Write(ServiceName);
                ClientPacket.PacketWriter.Write(FormattedText);

                if (LocalClient != null) { LocalClient.SendPacket(ClientPacket); }
            }
        }

        public static void LoadSHNs()
        {
            MethodInfo CryptoMethod = CSFile.LoadCode(Auth.ConfigValues["SHNCryptoFile"], "SHN.SHNCrypto", Auth.ConfigValues["SHNCryptoName"]);

            AbStateView = new SHNFile(String.Format("{0}AbStateView.shn", Auth.ConfigValues["ServerSHNPath"]), CryptoMethod);

            if (AbStateView.Type == SHNType.TextData) { AbStateView.SHNEncoding = Encoding.ASCII; }
            else { AbStateView.SHNEncoding = Encoding.GetEncoding("ISO-8859-1"); }

            if (AbStateView.Type != SHNType.QuestData) { AbStateView.Read(); }
            else { AbStateView.ReadQuest(); }

            ActiveSkill = new SHNFile(String.Format("{0}ActiveSkill.shn", Auth.ConfigValues["ServerSHNPath"]), CryptoMethod);

            if (ActiveSkill.Type == SHNType.TextData) { ActiveSkill.SHNEncoding = Encoding.ASCII; }
            else { ActiveSkill.SHNEncoding = Encoding.GetEncoding("ISO-8859-1"); }

            if (ActiveSkill.Type != SHNType.QuestData) { ActiveSkill.Read(); }
            else { ActiveSkill.ReadQuest(); }

            ActiveSkill.DisallowRowChanges();

            ItemInfo = new SHNFile(String.Format("{0}ItemInfo.shn", Auth.ConfigValues["ServerSHNPath"]), CryptoMethod);

            if (ItemInfo.Type == SHNType.TextData) { ItemInfo.SHNEncoding = Encoding.ASCII; }
            else { ItemInfo.SHNEncoding = Encoding.GetEncoding("ISO-8859-1"); }

            if (ItemInfo.Type != SHNType.QuestData) { ItemInfo.Read(); }
            else { ItemInfo.ReadQuest(); }

            ItemInfo.DisallowRowChanges();

            PassiveSkill = new SHNFile(String.Format("{0}PassiveSkill.shn", Auth.ConfigValues["ServerSHNPath"]), CryptoMethod);

            if (PassiveSkill.Type == SHNType.TextData) { PassiveSkill.SHNEncoding = Encoding.ASCII; }
            else { PassiveSkill.SHNEncoding = Encoding.GetEncoding("ISO-8859-1"); }

            if (PassiveSkill.Type != SHNType.QuestData) { PassiveSkill.Read(); }
            else { PassiveSkill.ReadQuest(); }

            PassiveSkill.DisallowRowChanges();

            ItemAbstateGroups = new SHNFile(String.Format("{0}ItemAbstateGroups.shn", Auth.ConfigValues["FilterSHNPath"]), CryptoMethod);

            if (ItemAbstateGroups.Type == SHNType.TextData) { ItemAbstateGroups.SHNEncoding = Encoding.ASCII; }
            else { ItemAbstateGroups.SHNEncoding = Encoding.GetEncoding("ISO-8859-1"); }

            if (ItemAbstateGroups.Type != SHNType.QuestData) { ItemAbstateGroups.Read(); }
            else { ItemAbstateGroups.ReadQuest(); }

            ItemAbstates = new SHNFile(String.Format("{0}ItemAbstates.shn", Auth.ConfigValues["FilterSHNPath"]), CryptoMethod);

            if (ItemAbstates.Type == SHNType.TextData) { ItemAbstates.SHNEncoding = Encoding.ASCII; }
            else { ItemAbstates.SHNEncoding = Encoding.GetEncoding("ISO-8859-1"); }

            if (ItemAbstates.Type != SHNType.QuestData) { ItemAbstates.Read(); }
            else { ItemAbstates.ReadQuest(); }

            WinnableAbstates = new SHNFile(String.Format("{0}WinnableAbstates.shn", Auth.ConfigValues["FilterSHNPath"]), CryptoMethod);

            if (WinnableAbstates.Type == SHNType.TextData) { WinnableAbstates.SHNEncoding = Encoding.ASCII; }
            else { WinnableAbstates.SHNEncoding = Encoding.GetEncoding("ISO-8859-1"); }

            if (WinnableAbstates.Type != SHNType.QuestData) { WinnableAbstates.Read(); }
            else { WinnableAbstates.ReadQuest(); }

            Rebirth = new SHNFile(String.Format("{0}Rebirth.shn", Auth.ConfigValues["FilterSHNPath"]), CryptoMethod);

            if (Rebirth.Type == SHNType.TextData) { Rebirth.SHNEncoding = Encoding.ASCII; }
            else { Rebirth.SHNEncoding = Encoding.GetEncoding("ISO-8859-1"); }

            if (Rebirth.Type != SHNType.QuestData) { Rebirth.Read(); }
            else { Rebirth.ReadQuest(); }

            AntiAutoSkillLearn = new SHNFile(String.Format("{0}AntiAutoSkillLearn.shn", Auth.ConfigValues["FilterSHNPath"]), CryptoMethod);

            if (AntiAutoSkillLearn.Type == SHNType.TextData) { AntiAutoSkillLearn.SHNEncoding = Encoding.ASCII; }
            else { AntiAutoSkillLearn.SHNEncoding = Encoding.GetEncoding("ISO-8859-1"); }

            if (AntiAutoSkillLearn.Type != SHNType.QuestData) { AntiAutoSkillLearn.Read(); }
            else { AntiAutoSkillLearn.ReadQuest(); }

            AntiAutoSkillLearn.DisallowRowChanges();

            AntiAutoPassiveLearn = new SHNFile(String.Format("{0}AntiAutoPassiveLearn.shn", Auth.ConfigValues["FilterSHNPath"]), CryptoMethod);

            if (AntiAutoPassiveLearn.Type == SHNType.TextData) { AntiAutoPassiveLearn.SHNEncoding = Encoding.ASCII; }
            else { AntiAutoPassiveLearn.SHNEncoding = Encoding.GetEncoding("ISO-8859-1"); }

            if (AntiAutoPassiveLearn.Type != SHNType.QuestData) { AntiAutoPassiveLearn.Read(); }
            else { AntiAutoPassiveLearn.ReadQuest(); }

            AntiAutoPassiveLearn.DisallowRowChanges();

            PartyAbstates = new SHNFile(String.Format("{0}PartyAbstates.shn", Auth.ConfigValues["FilterSHNPath"]), CryptoMethod);

            if (PartyAbstates.Type == SHNType.TextData) { PartyAbstates.SHNEncoding = Encoding.ASCII; }
            else { PartyAbstates.SHNEncoding = Encoding.GetEncoding("ISO-8859-1"); }

            if (PartyAbstates.Type != SHNType.QuestData) { PartyAbstates.Read(); }
            else { PartyAbstates.ReadQuest(); }

            PartyAbstates.DisallowRowChanges();

            foreach (DataRow Row in ItemInfo.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToByte(ItemArray.ItemArray[4]) == 11).ToList())
            {
                String InxName = Row.ItemArray[1].ToString();
                Byte DemandLv = Convert.ToByte(Row.ItemArray[9]);
                Int32 WhoEquip = Convert.ToInt32(Row.ItemArray[29]);
                Boolean IsMultiClass;
                Byte ClassID = Classes.ConvertToClassID(WhoEquip, out IsMultiClass);
                DataRow ActiveSkillRow;
                DataRow PassiveSkillRow;

                if ((ActiveSkillRow = ActiveSkill.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToString(ItemArray.ItemArray[1]) == InxName).FirstOrDefault()) != null)
                {
                    Int32 SkillID = Convert.ToInt32(ActiveSkillRow.ItemArray[0]);

                    if (!ClassSkills.ContainsKey(ClassID)) { ClassSkills.Add(ClassID, new List<Object[]>()); }

                    if (AntiAutoSkillLearn.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToInt32(ItemArray.ItemArray[0]) == SkillID).FirstOrDefault() == null)
                    {
                        if (ClassID != 0) { ClassSkills[ClassID].Add(new Object[] { DemandLv, SkillID }); }

                        if (ClassID != 0 && IsMultiClass) { ClassSkills[Convert.ToByte(ClassID + 1)].Add(new Object[] { DemandLv, SkillID }); }
                    }
                }

                if ((PassiveSkillRow = PassiveSkill.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToString(ItemArray.ItemArray[1]) == InxName).FirstOrDefault()) != null)
                {
                    Int32 PassiveID = Convert.ToInt32(PassiveSkillRow.ItemArray[0]);

                    if (!ClassPassives.ContainsKey(ClassID)) { ClassPassives.Add(ClassID, new List<Object[]>()); }

                    if (AntiAutoPassiveLearn.Table.Rows.Cast<DataRow>().Where(ItemArray => Convert.ToInt32(ItemArray.ItemArray[0]) == PassiveID).FirstOrDefault() == null)
                    {
                        if (ClassID != 0) { ClassPassives[ClassID].Add(new Object[] { DemandLv, PassiveID }); }

                        if (ClassID != 0 && IsMultiClass) { ClassPassives[Convert.ToByte(ClassID + 1)].Add(new Object[] { DemandLv, PassiveID }); }
                    }
                }
            }
        }
    }
}
