using System;
using TaleWorlds.CampaignSystem;
using TaleWorlds.CampaignSystem.GameMenus;
using TaleWorlds.CampaignSystem.Overlay;
using TaleWorlds.Localization;
using TaleWorlds.CampaignSystem.Actions;
using Helpers;
using TaleWorlds.CampaignSystem.SandBox.GameComponents.Party;
using System.Reflection;
using System.Linq;
using System.Xml.Linq;
using TaleWorlds.Core;
using TaleWorlds.ObjectSystem;

namespace Bannerlord.MedicalDistrict
{
	internal class MedicalDistrictBehaviors : CampaignBehaviorBase
    {
        public override void SyncData(IDataStore dataStore) { }
		public override void RegisterEvents()
		{
			CampaignEvents.OnSessionLaunchedEvent.AddNonSerializedListener(this, new Action<CampaignGameStarter>(this.OnSessionLaunched));
		}

		public void OnSessionLaunched(CampaignGameStarter campaignGameStarter)
		{
			AddGameMenus(campaignGameStarter);
		}

		public void AddGameMenus(CampaignGameStarter campaignGameStarter)
		{
			campaignGameStarter.AddGameMenuOption("town", "town_medical_district", "{=l9sFJawW}Go: Support Сenter", new GameMenuOption.OnConditionDelegate(game_menu_go_to_medical_district_on_condition), delegate (MenuCallbackArgs x)
			{
				GameMenu.SwitchToMenu("town_medical_district");
			}, false, 4, false);
			campaignGameStarter.AddGameMenu("town_medical_district", "You arrive at Support Сenter.", new OnInitDelegate(town_medical_district_on_init), GameOverlays.MenuOverlayType.SettlementWithBoth, GameMenu.MenuFlags.none, null);

			campaignGameStarter.AddGameMenuOption("town_medical_district", "town_medical_district_self_heal", "{=*}Heal (you): ({HEAL_SELF_AMOUNT}{GOLD_ICON})", new GameMenuOption.OnConditionDelegate(player_needs_heal_on_condition), delegate (MenuCallbackArgs x)
			{
				if (Hero.MainHero.Gold >= PriceToHeal(Hero.MainHero))
				{
					HealPlayerCharacter();
				};
			}, false, -1, false);
			campaignGameStarter.AddGameMenuOption("town_medical_district", "town_medical_district_companion_heal", "{=*}Heal (companions): ({HEAL_COMPANION_AMOUNT}{GOLD_ICON})", new GameMenuOption.OnConditionDelegate(companions_needs_heal_on_condition), delegate (MenuCallbackArgs x)
			{
				HealPartyCharacters(false);
			}, false, -1, false);
			campaignGameStarter.AddGameMenuOption("town_medical_district", "town_medical_district_player_and_companion_heal", "{=*}Heal (party): ({HEAL_ALL_AMOUNT}{GOLD_ICON})", new GameMenuOption.OnConditionDelegate(party_characters_needs_heal_on_condition), delegate (MenuCallbackArgs x)
			{
				HealPartyCharacters(true);
			}, false, -1, false);
			campaignGameStarter.AddGameMenuOption("town_medical_district", "town_medical_district_buy_renown", "{=*}Buy: 1 Renown {PRICE_RENOWN_AMOUNT}{GOLD_ICON}", new GameMenuOption.OnConditionDelegate(player_buys_renown_on_condition), delegate (MenuCallbackArgs x)
			{
				int price_renown = 100 + Hero.MainHero.Level * Hero.MainHero.Level;
				Hero.MainHero.Clan.AddRenown (1, true);
				GiveGoldAction.ApplyBetweenCharacters(null, Hero.MainHero, -price_renown, false);
			}, false, -1, false);
			campaignGameStarter.AddGameMenuOption("town_medical_district", "town_medical_district_buy_renown_10", "{=*}Buy: 10 Renown {PRICE_RENOWN_10_AMOUNT}{GOLD_ICON}", new GameMenuOption.OnConditionDelegate(player_buys_renown_10_on_condition), delegate (MenuCallbackArgs x)
			{
				int price_renown_10 = 10 * (100 + Hero.MainHero.Level * Hero.MainHero.Level);
				Hero.MainHero.Clan.AddRenown(10, true);
				GiveGoldAction.ApplyBetweenCharacters(null, Hero.MainHero, -price_renown_10, false);
			}, false, -1, false);
			campaignGameStarter.AddGameMenuOption("town_medical_district", "town_medical_district_buy_renown_100", "{=*}Buy: 100 Renown {PRICE_RENOWN_100_AMOUNT}{GOLD_ICON}", new GameMenuOption.OnConditionDelegate(player_buys_renown_100_on_condition), delegate (MenuCallbackArgs x)
			{
				int price_renown_100 = 100 * (100 + Hero.MainHero.Level * Hero.MainHero.Level);
				Hero.MainHero.Clan.AddRenown(100, true);
				GiveGoldAction.ApplyBetweenCharacters(null, Hero.MainHero, -price_renown_100, false);
			}, false, -1, false);
			campaignGameStarter.AddGameMenuOption("town_medical_district", "town_medical_district_buy_influence", "{=*}Buy: 1 Influence {PRICE_RENOWN_AMOUNT}{GOLD_ICON}", new GameMenuOption.OnConditionDelegate(player_buys_renown_on_condition), delegate (MenuCallbackArgs x)
			{
				int price_renown = 100 + Hero.MainHero.Level * Hero.MainHero.Level;
				Hero.MainHero.AddInfluenceWithKingdom(1);
				GiveGoldAction.ApplyBetweenCharacters(null, Hero.MainHero, -price_renown, false);
			}, false, -1, false);
			campaignGameStarter.AddGameMenuOption("town_medical_district", "town_medical_district_buy_influence_10", "{=*}Buy: 10 Influence {PRICE_RENOWN_10_AMOUNT}{GOLD_ICON}", new GameMenuOption.OnConditionDelegate(player_buys_renown_10_on_condition), delegate (MenuCallbackArgs x)
			{
				int price_renown_10 = 10*(100 + Hero.MainHero.Level * Hero.MainHero.Level);
				Hero.MainHero.AddInfluenceWithKingdom(10);
				GiveGoldAction.ApplyBetweenCharacters(null, Hero.MainHero, -price_renown_10, false);
			}, false, -1, false);
			campaignGameStarter.AddGameMenuOption("town_medical_district", "town_medical_district_buy_influence_100", "{=*}Buy: 100 Influence {PRICE_RENOWN_100_AMOUNT}{GOLD_ICON}", new GameMenuOption.OnConditionDelegate(player_buys_renown_10_on_condition), delegate (MenuCallbackArgs x)
			{
				int price_renown_100 = 100*(100 + Hero.MainHero.Level * Hero.MainHero.Level);
				Hero.MainHero.AddInfluenceWithKingdom(10);
				GiveGoldAction.ApplyBetweenCharacters(null, Hero.MainHero, -price_renown_100, false);
			}, false, -1, false);
			campaignGameStarter.AddGameMenuOption("town_medical_district", "town_medical_district_exchange_renown", "{=*}1 Renown on Influence", new GameMenuOption.OnConditionDelegate(player_exchange_renown_on_condition), delegate (MenuCallbackArgs x)
			{
				if (Hero.MainHero.Clan.Influence >= 1)
				{
					Hero.MainHero.Clan.AddRenown(1, true);
					Hero.MainHero.Clan.Influence -= 1;
				};
			}, false, -1, false);
//			campaignGameStarter.AddGameMenuOption("town_medical_district", "town_medical_district_exchange_renown_10", "{=*}Exchange: 10 Renown on Influence", new GameMenuOption.OnConditionDelegate(player_exchange_renown_10_on_condition), delegate (MenuCallbackArgs x)
//			{
//				if (Hero.MainHero.Clan.Influence >= 10)
//				{
//					Hero.MainHero.Clan.AddRenown(10, true);
//					Hero.MainHero.Clan.Influence -= 10;
//				};
//			}, false, -1, false);
			campaignGameStarter.AddGameMenuOption("town_medical_district", "town_medical_district_exchange_renown_all", "{=*}Renown on all Influence", new GameMenuOption.OnConditionDelegate(player_exchange_renown_all_on_condition), delegate (MenuCallbackArgs x)
			{
				if (Hero.MainHero.Clan.Influence >= 1)
				{
					Hero.MainHero.Clan.AddRenown(Hero.MainHero.Clan.Influence, true);
					Hero.MainHero.Clan.Influence = 0;
				};
			}, false, -1, false);
			campaignGameStarter.AddGameMenuOption("town_medical_district", "town_medical_district_exchange_influence", "{=*}1 Influence on Renown", new GameMenuOption.OnConditionDelegate(player_exchange_influence_on_condition), delegate (MenuCallbackArgs x)
			{
				if (Hero.MainHero.Clan.Renown >= 1)
				{
					Hero.MainHero.AddInfluenceWithKingdom(1);
					Hero.MainHero.Clan.Renown -= 1;
				};
			}, false, -1, false);
			campaignGameStarter.AddGameMenuOption("town_medical_district", "town_medical_district_exchange_influence_all", "{=*}Influence on Renown over 6150", new GameMenuOption.OnConditionDelegate(player_exchange_influence_all_on_condition), delegate (MenuCallbackArgs x)
			{
				if (Hero.MainHero.Clan.Renown > 6150)
				{
					float renown_to_influence = Hero.MainHero.Clan.Renown - 6150;
					Hero.MainHero.AddInfluenceWithKingdom(renown_to_influence);
					Hero.MainHero.Clan.Renown -= renown_to_influence;
				};
			}, false, -1, false);
			campaignGameStarter.AddGameMenuOption("town_medical_district", "town_medical_district_back", "{=qWAmxyYz}Back to town center", new GameMenuOption.OnConditionDelegate(back_on_condition), delegate (MenuCallbackArgs x)
			{
				GameMenu.SwitchToMenu("town");
			}, false, -1, false);
		}
		private bool game_menu_go_to_medical_district_on_condition(MenuCallbackArgs args)
		{
			args.optionLeaveType = GameMenuOption.LeaveType.Submenu;
			return MenuHelper.SetOptionProperties(args, true, false, TextObject.Empty);
		}
		private void town_medical_district_on_init(MenuCallbackArgs args)
		{
			args.MenuTitle = new TextObject("Medical District", null);
		}

		// Buy Renown or Influence
		private bool player_buys_renown_on_condition(MenuCallbackArgs args)
		{
			int price_renown = 100 + Hero.MainHero.Level * Hero.MainHero.Level;
			MBTextManager.SetTextVariable("PRICE_RENOWN_AMOUNT", price_renown);
			if (Hero.MainHero.Gold >= price_renown && Hero.MainHero.Clan.Renown < 6150)
			{
				args.optionLeaveType = GameMenuOption.LeaveType.RansomAndBribe;
				return true;
			};
			return false;
		}

		private bool player_buys_renown_10_on_condition(MenuCallbackArgs args)
		{
			int price_renown_10 = 10*(100 + Hero.MainHero.Level * Hero.MainHero.Level);
			MBTextManager.SetTextVariable("PRICE_RENOWN_10_AMOUNT", price_renown_10);
			if (Hero.MainHero.Gold >= price_renown_10 && Hero.MainHero.Clan.Renown < 6150)
			{
				args.optionLeaveType = GameMenuOption.LeaveType.RansomAndBribe;
				return true;
			};
			return false;
		}
		private bool player_buys_renown_100_on_condition(MenuCallbackArgs args)
		{
			int price_renown_100 = 100*(100 + Hero.MainHero.Level * Hero.MainHero.Level);
			MBTextManager.SetTextVariable("PRICE_RENOWN_100_AMOUNT", price_renown_100);
			if (Hero.MainHero.Gold >= price_renown_100 && Hero.MainHero.Clan.Renown < 6150)
			{
				args.optionLeaveType = GameMenuOption.LeaveType.RansomAndBribe;
				return true;
			};
			return false;
		}

		private bool player_exchange_renown_on_condition(MenuCallbackArgs args)
		{
			if (Hero.MainHero.Clan.Influence >= 1)
			{
				return true;
			};
			return false;
		}
//		private bool player_exchange_renown_10_on_condition(MenuCallbackArgs args)
//		{
//			if (Hero.MainHero.Clan.Influence >= 10)
//			{
//				return true;
//			};
//			return false;
//		}

		private bool player_exchange_renown_all_on_condition(MenuCallbackArgs args)
		{
			if (Hero.MainHero.Clan.Influence >= 1)
			{
				return true;
			};
			return false;
		}

		private bool player_exchange_influence_on_condition(MenuCallbackArgs args)
		{
			if (Hero.MainHero.Clan.Renown >= 1)
			{
				return true;
			};
			return false;
		}
		private bool player_exchange_influence_all_on_condition(MenuCallbackArgs args)
		{
			if (Hero.MainHero.Clan.Renown > 6150)
			{
				return true;
			};
			return false;
		}

//
		private bool player_needs_heal_on_condition(MenuCallbackArgs args)
		{
			if (Hero.MainHero.HitPoints < Hero.MainHero.MaxHitPoints)
			{
				int price = PriceToHeal(Hero.MainHero);
				MBTextManager.SetTextVariable("HEAL_SELF_AMOUNT", price);
				args.optionLeaveType = GameMenuOption.LeaveType.RansomAndBribe;
				return true;
			}
			return false;
		}

		private void HealPlayerCharacter()
		{
			int price = PriceToHeal(Hero.MainHero);
			Hero.MainHero.HitPoints = Hero.MainHero.MaxHitPoints;
			GiveGoldAction.ApplyBetweenCharacters(null, Hero.MainHero, -price, false);
			GameMenu.SwitchToMenu("town_medical_district");
		}

		private bool companions_needs_heal_on_condition(MenuCallbackArgs args)
		{
			int numberInjured = 0;
			int price = 0;
			CalculatePriceAndNumInjured(ref price, ref numberInjured, false, false);
			if (numberInjured > 0)
			{
				MBTextManager.SetTextVariable("HEAL_COMPANION_AMOUNT", price);
				args.optionLeaveType = GameMenuOption.LeaveType.RansomAndBribe;
				return true;
			}
			return false;
		}

		private bool party_characters_needs_heal_on_condition(MenuCallbackArgs args)
		{
			int numberInjured = 0;
			int price = 0;
			CalculatePriceAndNumInjured(ref price, ref numberInjured, true, false);
			if (numberInjured > 1 && Hero.MainHero.HitPoints < Hero.MainHero.MaxHitPoints)
			{
				MBTextManager.SetTextVariable("HEAL_ALL_AMOUNT", price);
				args.optionLeaveType = GameMenuOption.LeaveType.RansomAndBribe;
				return true;
			}
			return false;
		}

		private void HealPartyCharacters(bool healplayer)
		{
			int numberTreated = 0;
			int price = 0;
			CalculatePriceAndNumInjured(ref price, ref numberTreated, healplayer, true);
			if (numberTreated > 0)
			{
				GiveGoldAction.ApplyBetweenCharacters(null, Hero.MainHero, -price, false);
			}
			GameMenu.SwitchToMenu("town_medical_district");
		}

		private bool back_on_condition(MenuCallbackArgs args)
		{
			args.optionLeaveType = GameMenuOption.LeaveType.Leave;
			return true;
		}

		private int PriceToHeal(Hero hero)
		{
			double basePrice = 100;
			double percentHpMissing = (double)(hero.MaxHitPoints - hero.HitPoints)/hero.MaxHitPoints;
			return Convert.ToInt32(basePrice * percentHpMissing);
		}

		private void CalculatePriceAndNumInjured(ref int price, ref int numberTreated, bool includeMainHero, bool restoreHealth)
		{
			TroopRoster memberRoster = MobileParty.MainParty.MemberRoster;
			if (memberRoster.TotalHeroes > 0)
			{
				for (int i = 0; i < memberRoster.Count; i++)
				{
					Hero heroObject = memberRoster.GetCharacterAtIndex(i).HeroObject;
					if (heroObject != null)
					{
						if (heroObject.HitPoints < heroObject.MaxHitPoints && (includeMainHero || heroObject != Hero.MainHero))
						{
							numberTreated++;
							price += PriceToHeal(heroObject);
							if (restoreHealth)
							{
								heroObject.HitPoints = heroObject.MaxHitPoints;
							}
						}
					}
				}
			}
		}
	}
}