using System;
using System.Reflection;
using System.Collections.Generic;
using NCMS;
using UnityEngine;
using UnityEngine.UI;
using ReflectionUtility;
using HarmonyLib;
using ai;
using ai.behaviours;
using Newtonsoft.Json.Linq;

namespace Diplomacy_Army
{
    [ModEntry]
    public class Main : MonoBehaviour
    {

        public Harmony harmony;
        public static WorldTile worldTile;
        public static Kingdom kingdom;
        public static City city;
        public static PowerButton selectedPowerButton;

        public static Dictionary<Kingdom, Dictionary<string,DateTime>> KingdomMessages = new Dictionary<Kingdom, Dictionary<string, DateTime>>();
        public static List<string> messagesOutTime = new List<string>();
        public static List<Kingdom> kingdomsOutTime = new List<Kingdom>();
        public static string text = "";
        public static int index = 0;
        public Rect rect = new Rect(0, 0, 156f, 20f);
        public GUIContent content = new GUIContent();
        public Vector3 vector3 = new Vector3();
        public Vector3 position = new Vector3();
        public Vector3 position2 = new Vector3();

        public static DateTime celebrationTime = DateTime.MinValue;

        public static Dictionary<string, Treaty> treaties = new Dictionary<string, Treaty>();
        public static Kingdom kingdom1;
        public static Kingdom kingdom2;
        public static Color kingdom1_color;
        public static Color kingdom2_color;
        public static Color text_color;
        public static string[] array = new string[3];
        public static string text2 = "";

        public static ZoneCalculator zoneCalculator;
        public static TileZone[,] map;
        public static int max_x;
        public static int max_y;

        public static bool showWorldLow = false;
        public static bool isWindowActive = false;
        public void Awake()
        {
            harmony = new Harmony("10011011");
            MoreGodPower.init();
            KingdomPowerWindow.init();
            CityPowerWindow.init();
            ArmyPowerWindow.init();
            DiplomacyPowerWindow.init();
            WorldLowPowerWindow.init();
            foreach (ResourceAsset resourceAsset in AssetManager.resources.list)
            {
                resourceAsset.maximum = 99999;
            }
            Patching(harmony);
        }

        public void Update()
        {
            updateTreaty();
            updateCities();
        }

        public void OnGUI()
        {
            if (!ScrollWindow.isWindowActive())
            {
                if (KingdomMessages.Count > 0 && MoreGodPower.toggles["显示外交消息"])
                {
                    GUI.skin.label.fontSize = 13;
                    GUI.skin.label.fontStyle = FontStyle.Bold;
                    GUI.skin.label.alignment = TextAnchor.MiddleLeft;
                    GUI.skin.label.normal.textColor = Color.black;
                    GUI.skin.label.normal.background = Texture2D.whiteTexture;
                    #region 显示外交消息
                    foreach (var item in KingdomMessages)
                    {
                        Kingdom kingdom = item.Key;
                        if (!kingdom.alive)
                        {
                            KingdomMessages.Remove(item.Key);
                            break;
                        }
                        if (KingdomMessages[kingdom].Count > 0)
                        {
                            text = "";
                            index = 0;
                            foreach (var item2 in KingdomMessages[kingdom])
                            {
                                if (DateTime.Compare(item2.Value, DateTime.Now.ToLocalTime()) > 0)
                                {
                                    if (index > 0)
                                    {
                                        text += "\r\n";
                                    }
                                    index += (11 + item2.Key.Length) / 12;
                                    text += item2.Key;
                                }
                                else
                                {
                                    messagesOutTime.Add(item2.Key);
                                }
                            }
                            if (messagesOutTime.Count > 0)
                            {
                                foreach (string meg in messagesOutTime)
                                {
                                    KingdomMessages[kingdom].Remove(meg);
                                }
                                messagesOutTime.Clear();
                            }
                            if (text != "" && kingdom.capital != null)
                            {
                                vector3 = (Vector3)(Reflection.GetField(kingdom.capital.GetType(), kingdom.capital, "cityCenter"));
                                position = Camera.main.WorldToScreenPoint(vector3);
                                position.y = Screen.height - position.y;
                                rect.width = 156f;
                                rect.height = 20f * (index + 0.2f);
                                rect.y = position.y - rect.height - 14f;
                                rect.x = position.x - rect.width / 2;
                                GUI.Label(rect, text);
                            }
                        }
                        else
                        {
                            kingdomsOutTime.Add(kingdom);
                        }
                    }
                    if (kingdomsOutTime.Count > 0)
                    {
                        foreach (Kingdom kingdom2 in kingdomsOutTime)
                        {
                            KingdomMessages.Remove(kingdom2);
                        }
                        kingdomsOutTime.Clear();
                    }
                    #endregion
                }
                if (treaties.Count > 0 && MoreGodPower.toggles["显示条约"])
                {
                    GUI.skin.box.fontStyle = FontStyle.Bold;
                    GUI.skin.box.alignment = TextAnchor.MiddleLeft;
                    GUI.skin.box.fontSize = 13;
                    GUI.skin.box.richText = true;

                    zoneCalculator = Reflection.GetField(MapBox.instance.GetType(), MapBox.instance, "zoneCalculator") as ZoneCalculator;
                    map = Reflection.GetField(zoneCalculator.GetType(), zoneCalculator, "map") as TileZone[,];

                    vector3 = map[map.GetLength(0) - 1, map.GetLength(1) - 1].centerTile.posV3;
                    position = Camera.main.WorldToScreenPoint(vector3);
                    position.y = Screen.height - position.y;
                    position.x += 20f;
                    rect.width = 500f;
                    rect.height = 20f;
                    rect.x = position.x;
                    rect.y = position.y;
                    foreach (var item in treaties)
                    {
                        if (item.Value.endTime < MapBox.instance.mapStats.year)
                        {
                            treaties.Remove(item.Key);
                            break;
                        }
                        kingdom1 = item.Value.kingdom_1;
                        kingdom2 = item.Value.kingdom_2;
                        if (kingdom1 == null || kingdom2 == null || !MapBox.instance.kingdoms.list_civs.Contains(kingdom1) || !MapBox.instance.kingdoms.list_civs.Contains(kingdom2))
                        {
                            treaties.Remove(item.Key);
                            break;
                        }
                        kingdom1_color = ((KingdomColor)Reflection.GetField(kingdom1.GetType(), kingdom1, "kingdomColor")).colorBorderOut;
                        kingdom2_color = ((KingdomColor)Reflection.GetField(kingdom2.GetType(), kingdom2, "kingdomColor")).colorBorderOut;
                        if (kingdom1_color != item.Value.kingdom1_color || kingdom2_color != item.Value.kingdom2_color
                            || kingdom1.name != item.Value.kingdom1_name || kingdom2.name != item.Value.kingdom2_name)
                        {
                            item.Value.Change();
                        }
                        GUI.skin.box.normal.textColor = item.Value.color;
                        GUI.Box(rect, item.Value.message);
                        rect.y += 20f;
                    }
                }
                if (MapBox.instance.kingdoms.list_civs.Count > 0 && MoreGodPower.toggles["显示交战"])
                {
                    GUI.skin.box.fontSize = 13;
                    GUI.skin.box.fontStyle = FontStyle.Bold;
                    GUI.skin.box.alignment = TextAnchor.MiddleLeft;
                    zoneCalculator = Reflection.GetField(MapBox.instance.GetType(), MapBox.instance, "zoneCalculator") as ZoneCalculator;
                    map = Reflection.GetField(zoneCalculator.GetType(), zoneCalculator, "map") as TileZone[,];

                    vector3 = map[0, map.GetLength(1) - 1].centerTile.posV3;
                    position = Camera.main.WorldToScreenPoint(vector3);
                    position.y = Screen.height - position.y;
                    vector3 = map[0, 0].centerTile.posV3;
                    position2 = Camera.main.WorldToScreenPoint(vector3);
                    position2.y = Screen.height - position.y;
                    rect.width = 250f;
                    rect.height = 20f;
                    rect.x = position.x - rect.width - 20f;
                    rect.y = position.y;
                    foreach (Kingdom kingdom in MapBox.instance.kingdoms.list_civs)
                    {
                        if (kingdom.civs_enemies.Count > 0)
                        {
                            GUI.skin.box.normal.textColor = ((KingdomColor)Reflection.GetField(kingdom.GetType(), kingdom, "kingdomColor")).colorBorderOut;
                            foreach (Kingdom kingdom2 in kingdom.civs_enemies.Keys)
                            {
                                text = "【" + kingdom.name + "】与【" + kingdom2.name + "】交战中";
                                GUI.Box(rect, text);
                                rect.y += 20f;
                                if (rect.y > position2.y)
                                {
                                    rect.y = position.y;
                                    rect.x -= rect.width;
                                }
                            }
                        }
                    }
                }
            }

            if (showWorldLow)
            {
                GUI.skin.box.fontSize = 13;
                GUI.skin.box.fontStyle = FontStyle.Bold;
                GUI.skin.box.alignment = TextAnchor.MiddleLeft;
                GUI.skin.box.normal.textColor = Color.white;
                rect.x = 709f;
                rect.y = 180f;
                rect.width = 50f;
                rect.height = 20f;
                foreach (var item in MoreGodPower.toggles)
                {
                    if (item.Value)
                    {
                        GUI.Box(rect, "已开启");
                    }
                    rect.x += 114f;
                }
            }
        }

        public static void updateTreaty()
        {
            NewFunction.updateTreaty(MoreGodPower.AllianceKingdoms, "互不侵犯", true);
            NewFunction.updateTreaty(MoreGodPower.DefenceKingdoms, "共同防御");
            NewFunction.updateTreaty(MoreGodPower.ArmyKingdoms, "军事通行");
        }
        public static void updateCities()
        {
            if (MoreGodPower.citiesCelebrate.Count > 0 && DateTime.Compare(celebrationTime, DateTime.Now.ToLocalTime()) < 0)
            {
                foreach(City city in MoreGodPower.citiesCelebrate)
                {
                    if (city.getTile() != null)
                    {
                        MapBox.instance.stackEffects.CallMethod("spawnFireworks", city.getTile(), 0f);
                        MoreGodPower.citiesCelebrate.Remove(city);
                        celebrationTime = DateTime.Now.ToLocalTime().AddSeconds(0.2);
                        break;
                    }
                }
            }
        }

        #region patch
        public static void Patching(Harmony harmony)
        {
            Utils.HarmonyPatching(harmony, "prefix", AccessTools.Method(typeof(PowerButton), "unselectActivePower"), AccessTools.Method(typeof(Main), "unselectActivePower_Prefix"));
            Debug.Log("Prefix: PowerButton.unselectActivePower");

            Utils.HarmonyPatching(harmony, "prefix", AccessTools.Method(typeof(DiplomacyManager), "startWar"), AccessTools.Method(typeof(Main), "startWar_Prefix"));
            Debug.Log("Prefix: DiplomacyManager.startWar");

            Utils.HarmonyPatching(harmony, "postfix", AccessTools.Method(typeof(DiplomacyManager), "startWar"), AccessTools.Method(typeof(Main), "startWar_Postfix"));
            Debug.Log("Postfix: DiplomacyManager.startWar");

            Utils.HarmonyPatching(harmony, "postfix", AccessTools.Method(typeof(DiplomacyManager), "startPeace"), AccessTools.Method(typeof(Main), "startPeace_Postfix"));
            Debug.Log("Postfix: DiplomacyManager.startPeace");

            Utils.HarmonyPatching(harmony, "prefix", AccessTools.Method(typeof(KingdomCheckDiplomacy), "execute"), AccessTools.Method(typeof(Main), "execute_Prefix"));
            Debug.Log("Postfix: KingdomCheckDiplomacy.execute");

            Utils.HarmonyPatching(harmony, "postfix", AccessTools.Method(typeof(KingdomCheckDiplomacy), "execute"), AccessTools.Method(typeof(Main), "execute_Postfix"));
            Debug.Log("Postfix: KingdomCheckDiplomacy.execute");

            Utils.HarmonyPatching(harmony, "postfix", AccessTools.Method(typeof(KingdomOpinion), "calculate"), AccessTools.Method(typeof(Main), "calculate_Postfix"));
            Debug.Log("Postfix: KingdomOpinion.calculate");

            Utils.HarmonyPatching(harmony, "postfix", AccessTools.Method(typeof(ActorMove), "goTo"), AccessTools.Method(typeof(Main), "goTo_Postfix"));
            Debug.Log("Postfix: ActorMove.goto");

            Utils.HarmonyPatching(harmony, "postfix", AccessTools.Method(typeof(ScrollWindow), "setActive"), AccessTools.Method(typeof(Main), "setActive_Postfix"));
            Debug.Log("Postfix: ScrollWindow.setActive");

            //Utils.HarmonyPatching(harmony, "postfix", AccessTools.Method(typeof(Kingdom), "isEnemy"), AccessTools.Method(typeof(Main), "isEnemy_Postfix"));
            //Debug.Log("Postfix: Kingdom.isEnemy");

            //Utils.HarmonyPatching(harmony, "prefix", AccessTools.Method(typeof(KingdomManager), "setDiplomacyState"), AccessTools.Method(typeof(Main), "setDiplomacyState_Prefix"));
            //Debug.Log("Prefix: KingdomManager.setDiplomacyState");
        }

        public static void unselectActivePower_Prefix()
        {
            if (MoreGodPower.selected_kingdom != null || MoreGodPower.selected_city != null)
            {
                MoreGodPower.selected_kingdom = null;
                MoreGodPower.selected_city = null;
                NewFunction.AddNewText("已取消操作", Toolbox.color_log_neutral);
            }
        }
        public static bool startWar_Prefix(Kingdom pKingdom, Kingdom tTarget, bool pForced = false)
        {
            if (MoreGodPower.AllianceKingdoms.ContainsKey(pKingdom) && MoreGodPower.AllianceKingdoms[pKingdom].ContainsKey(tTarget))
            {
                NewFunction.LogNewMessage(pKingdom, tTarget, "", "与", "签订了互不侵犯条约，无法开战");
                return false;
            }
            if (MoreGodPower.DefenceKingdoms.ContainsKey(pKingdom) && MoreGodPower.DefenceKingdoms[pKingdom].ContainsKey(tTarget))
            {
                NewFunction.designTreaty(MoreGodPower.DefenceKingdoms, pKingdom, tTarget, "共同防御", false);
                NewFunction.LogNewMessage(pKingdom, tTarget, "", "撕毁了与", "签订的共同防御条约");
            }
            if (pKingdom.capital != null)
            {
                if (pKingdom.capital.getTile() != null)
                {
                    NewFunction.LogNewMessage(pKingdom, "对" + tTarget.name + "宣战");
                    NewFunction.LogNewMessage(tTarget, pKingdom.name + "对我方宣战");
                    Sfx.play("lightning", true, -1f, -1f);
                    //MapBox.spawnLightning(pKingdom.capital.getTile(), 0f);
                }
            }
            return true;
        }
        public static void startWar_Postfix(Kingdom pKingdom, Kingdom tTarget, bool pForced = false)
        {
            if (MoreGodPower.DefenceKingdoms.ContainsKey(tTarget) && MoreGodPower.DefenceKingdoms[tTarget].Count > 0 && tTarget.civs_enemies.ContainsKey(pKingdom))
            {
                foreach (var item in MoreGodPower.DefenceKingdoms[tTarget])
                {
                    if (item.Key.alive && !item.Key.civs_enemies.ContainsKey(pKingdom))
                    {
                        MapBox.instance.kingdoms.diplomacyManager.CallMethod("startWar", item.Key, pKingdom, false);
                    }
                }
            }
        }
        public static void startPeace_Postfix(Kingdom pKingdom, Kingdom tTarget, bool pForced = false)
        {
            if (pForced)
            {
                return;
            }
            if (tTarget.capital != null)
            {
                MoreGodPower.citiesCelebrate.Add(tTarget.capital);
            }
            NewFunction.LogNewMessage(pKingdom, "与" + tTarget.name + "达成和平");
            NewFunction.LogNewMessage(tTarget, "与" + pKingdom.name + "达成和平");
        }
        public static bool execute_Prefix(Kingdom pKingdom, ref BehResult __result)
        {
            if (MoreGodPower.KingdomsOwnedByPlayer.Contains(pKingdom))
            {
                __result = BehResult.Stop;
                return false;
            }
            return true;
        }
        public static void execute_Postfix(Kingdom pKingdom, ref BehResult __result)
        {
            if (!MoreGodPower.toggles["更多外交"] || __result == BehResult.Stop ||
                MoreGodPower.KingdomsOwnedByPlayer.Contains(pKingdom) || MapBox.instance.kingdoms.list_civs.Count < 2)
            {
                return;
            }
            NewFunction.tryNewTreaty(pKingdom);
        }
        public static void calculate_Postfix(Kingdom pMain, Kingdom pTarget, DiplomacyRelation pRelation, KingdomOpinion __instance)
        {
            int _opinion_total = (int)Traverse.Create(__instance).Field("_opinion_total").GetValue(); 
            int _opinion_far_lands = (int)Traverse.Create(__instance).Field("_opinion_far_lands").GetValue();
            int _opinion_close_borders = (int)Traverse.Create(__instance).Field("_opinion_close_borders").GetValue();
            switch (_opinion_far_lands)
            {
                case 35:
                    _opinion_far_lands = 60;
                    _opinion_total += 25;
                    break;
                case 60:
                    _opinion_far_lands = 35;
                    _opinion_total -= 25;
                    break;
                default:
                    _opinion_close_borders = -20;
                    _opinion_total += 30;
                    break;
            }
            int _opinion_is_supreme = (int)Traverse.Create(__instance).Field("_opinion_is_supreme").GetValue();
            if (_opinion_is_supreme == -100)
            {
                switch (_opinion_far_lands)
                {
                    case 35:
                        _opinion_is_supreme = -50;
                        _opinion_total += 50;
                        break;
                    case 60:
                        _opinion_is_supreme = -20;
                        _opinion_total += 80;
                        break;
                    default:
                        break;
                }
            }
            Traverse.Create(__instance).Field("_opinion_total").SetValue(_opinion_total);
            Traverse.Create(__instance).Field("_opinion_is_supreme").SetValue(_opinion_is_supreme);
            Traverse.Create(__instance).Field("_opinion_far_lands").SetValue(_opinion_far_lands);
            Traverse.Create(__instance).Field("_opinion_close_borders").SetValue(_opinion_close_borders);
        }
        public static void goTo_Postfix(Actor actor, ref ExecuteEvent __result, WorldTile target, bool pPathOnLiquid = false, bool pWalkOnBlocks = false)
        {
            if (__result == ExecuteEvent.True && actor.current_path.Count > 2 && actor.city != null && target.zone.city != null
                && MoreGodPower.toggles["封锁边境"] && !actor.stats.isBoat)
            {
                kingdom = Reflection.GetField(actor.city.GetType(), actor.city, "kingdom") as Kingdom;
                Kingdom kingdom2 = Reflection.GetField(target.zone.city.GetType(), target.zone.city, "kingdom") as Kingdom;
                if (kingdom != kingdom2 && kingdom.isCiv() && kingdom2.isCiv())
                {
                    foreach (WorldTile worldTile in actor.current_path)
                    {
                        if (worldTile.zone.city != null)
                        {
                            kingdom2 = Reflection.GetField(worldTile.zone.city.GetType(), worldTile.zone.city, "kingdom") as Kingdom;

                            if (kingdom2 != null && kingdom != kingdom2 && !kingdom.civs_enemies.ContainsKey(kingdom2) && !MoreGodPower.KingdomsOwnedByPlayer.Contains(kingdom2)
                                && !(MoreGodPower.ArmyKingdoms.ContainsKey(kingdom) && MoreGodPower.ArmyKingdoms[kingdom].ContainsKey(kingdom2)))
                            {
                                actor.CallMethod("setTileTarget", actor.city.getTile());
                                actor.current_path.Clear();
                                __result = ExecuteEvent.False;
                                if (!MoreGodPower.ArmyKingdoms.ContainsKey(kingdom))
                                {
                                    if (!MoreGodPower.KingdomsTryArmy.ContainsKey(kingdom))
                                    {
                                        MoreGodPower.KingdomsTryArmy.Add(kingdom, new List<Kingdom>());
                                    }
                                    MoreGodPower.KingdomsTryArmy[kingdom].Add(kingdom2);
                                }
                                return;
                            }
                        }
                    }
                }
            }
        }
        public static void isEnemy_Postfix(Kingdom pKingdom, ref bool __result, Kingdom __instance)
        {
            if (kingdom == null || __instance == null)
            {
                return;
            }
            if (__result && kingdom.isCiv() && __instance.isCiv())
            {
                __result = __instance != pKingdom && __instance.enemies.ContainsKey(pKingdom) && __instance.enemies[pKingdom];
            }
        }
        public static bool setDiplomacyState_Prefix(Kingdom k1, Kingdom k2, DiplomacyState pState)
        {
            if (pState == DiplomacyState.War && !k1.allies.ContainsKey(k2))
            {
                return false;
            }
            return true;
        }
        public static void setActive_Postfix(bool pActive, ScrollWindow __instance)
        {
            if (!pActive && __instance.screen_id.Equals("WorldLowControlWindow"))
            {
                showWorldLow = false;
            }
        }

    }

    public class Utils
    {
        public static void HarmonyPatching(Harmony harmony, string type, MethodInfo original, MethodInfo patch)
        {
            switch (type)
            {
                case "prefix":
                    harmony.Patch(original, prefix: new HarmonyMethod(patch));
                    break;
                case "postfix":
                    harmony.Patch(original, postfix: new HarmonyMethod(patch));
                    break;
            }
        }
        #endregion

    }
}
