using System;
using System.Collections.Generic;
using System.Globalization;
using Net.Eagle0.Eagle.Api.Command.Util;
using Net.Eagle0.Eagle.Common;
using Net.Eagle0.Eagle.Views;
using UnityEngine;
using static Net.Eagle0.Eagle.Common.QuestDetails;

namespace eagle {
    public class DisplayNames {
        public static bool DisplayFactionName {
            get => PlayerPrefs.GetInt("DisplayFactionName", 1) != 0;
            set => PlayerPrefs.SetInt("DisplayFactionName", value? 1: 0);
        }

        public static readonly Dictionary<Profession, string> ProfessionNames = new() {
            { Profession.NoProfession, "None" },
            { Profession.Engineer, "Engineer" },
            { Profession.Mage, "Mage" },
            { Profession.Necromancer, "Necromancer" },
            { Profession.Paladin, "Paladin" },
            { Profession.Ranger, "Ranger" },
            { Profession.Champion, "Champion" }
        };

        public static readonly Dictionary<Profession, string> ShortProfessionNames = new() {
            { Profession.NoProfession, "None" },
            { Profession.Engineer, "Engr" },
            { Profession.Mage, "Mage" },
            { Profession.Necromancer, "Necr" },
            { Profession.Paladin, "Pldn" },
            { Profession.Ranger, "Rngr" },
            { Profession.Champion, "Chmp" }
        };

        public static readonly Dictionary<BattalionTypeId, string> LongBattalionTypeNames = new() {
            { BattalionTypeId.LightInfantry, "Light Infantry" },
            { BattalionTypeId.HeavyInfantry, "Heavy Infantry" },
            { BattalionTypeId.LightCavalry, "Light Cavalry" },
            { BattalionTypeId.HeavyCavalry, "Heavy Cavalry" },
            { BattalionTypeId.Longbowmen, "Longbowmen" }
        };

        public static readonly Dictionary<BattalionTypeId, string> ShortBattalionTypeNames = new() {
            { BattalionTypeId.LightInfantry, "L Infantry" },
            { BattalionTypeId.HeavyInfantry, "H Infantry" },
            { BattalionTypeId.LightCavalry, "L Cavalry" },
            { BattalionTypeId.HeavyCavalry, "H Cavalry" },
            { BattalionTypeId.Longbowmen, "Longbowmen" }
        };

        public static readonly Dictionary<ProvinceOrderType, string> ProvinceOrderTypeNames =
                new() {
                    { ProvinceOrderType.Develop, "Develop" },
                    { ProvinceOrderType.Expand, "Expand" },
                    { ProvinceOrderType.Mobilize, "Mobilize" },
                    { ProvinceOrderType.Entrust, "Entrust" }
                };

        public static readonly Dictionary<CapturedHeroOption, string> CapturedHeroOptionNames =
                new() {
                    { CapturedHeroOption.RecruitCapturedHeroOption, "Recruit" },
                    { CapturedHeroOption.ImprisonCapturedHeroOption, "Imprison" },
                    { CapturedHeroOption.ExileCapturedHeroOption, "Exile" },
                    { CapturedHeroOption.ExecuteCapturedHeroOption, "Execute" },
                    { CapturedHeroOption.ReturnCapturedHeroOption, "Return" }
                };

        public static string PrisonerManagementTypeName(PrisonerManagementOption option) {
            switch (option.SealedValueCase) {
                case PrisonerManagementOption.SealedValueOneofCase.Execute: return "Execute";
                case PrisonerManagementOption.SealedValueOneofCase.Move: return "Move";
                case PrisonerManagementOption.SealedValueOneofCase.Exile: return "Exile";
                case PrisonerManagementOption.SealedValueOneofCase.Release: return "Release";
                case PrisonerManagementOption.SealedValueOneofCase.Return: return "Return";
                default: return "";
            }
        }

        public static string RecruitmentStatusString(string name, RecruitmentInfo recruitmentInfo) {
            switch (recruitmentInfo.Status) {
                case RecruitmentStatus.LowPrestige:
                    return $"You need more prestige before you can seek {name}'s favor.";

                case RecruitmentStatus.WouldJoin: return $"{name} would already gladly join you.";

                case RecruitmentStatus.NotDivined:
                    return $"You need to divine to learn {name}'s wishes.";

                case RecruitmentStatus.Outlaw:
                    return $"{name} is an outlaw. They might join you under the right circumstances.";

                case RecruitmentStatus.Exile:
                    return $"{name} is an exile. They might join you under the right circumstances.";

                case RecruitmentStatus.Prisoner:
                    return $"{name} is imprisoned and won't know of your deeds.";

                case RecruitmentStatus.MovingPrisoner:
                    return $"{name} is a prisoner being moved to another province.";

                case RecruitmentStatus.Traveler:
                    return $"{name} is unlikely to stay here long enough to impress with a quest.";

                case RecruitmentStatus.Sworn: return $"{name} is dedicated to another faction.";
            }

            return $"Unknown!";
        }

        public static string ShortRecruitmentStatusString(RecruitmentInfo recruitmentInfo) {
            switch (recruitmentInfo.Status) {
                case RecruitmentStatus.LowPrestige: return "Not enough prestige";

                case RecruitmentStatus.WouldJoin: return "Ready to join";

                case RecruitmentStatus.NotDivined: return "Not divined";

                case RecruitmentStatus.Outlaw: return "Outlaw";

                case RecruitmentStatus.Exile: return "Exile";

                case RecruitmentStatus.Prisoner: return "Prisoner";

                case RecruitmentStatus.MovingPrisoner: return "Moving Prisoner";

                case RecruitmentStatus.Traveler: return "Traveler";

                case RecruitmentStatus.Sworn: return "Dedicated to another faction";
            }

            return $"Unknown!";
        }

        public static string QuestTypeString(Quest quest) {
            switch (quest.Details.SealedValueCase) {
                case SealedValueOneofCase.DefeatFactionQuest: return "Attack Faction";
                case SealedValueOneofCase.DismissSpecificVassalQuest: return "Dismiss Vassal";
                case SealedValueOneofCase.AllianceQuest: return "Secure Alliance";
                case SealedValueOneofCase.AlmsToProvinceQuest: return "Give Alms in Province";
                case SealedValueOneofCase.AlmsAcrossRealmQuest: return "Give Alms Across Realm";
                case SealedValueOneofCase.GiveToHeroesInProvinceQuest:
                    return "Give to Heroes in Province";
                case SealedValueOneofCase.GiveToHeroesAcrossRealmQuest:
                    return "Give to Heroes Across Realm";
                case SealedValueOneofCase.ImproveAgricultureQuest: return "Improve Agriculture";
                case SealedValueOneofCase.ImproveEconomyQuest: return "Improve Economy";
                case SealedValueOneofCase.ImproveInfrastructureQuest:
                    return "Improve Infrastructure";
                case SealedValueOneofCase.UpgradeBattalionQuest: return "Great Battalion";
                case SealedValueOneofCase.GrandArmyQuest: return "Grand Army";
                case SealedValueOneofCase.SpecificExpansionQuest: return "Expand to Province";
                case SealedValueOneofCase.WealthQuest: return "Accumulate Wealth";
                case SealedValueOneofCase.TruceWithFactionQuest: return "Truce with Faction";
                case SealedValueOneofCase.TruceCountQuest: return "Truce Count";
                case SealedValueOneofCase.FreePrisonerQuest: return "Free Prisoner";
                case SealedValueOneofCase.ReturnPrisonerQuest: return "Return Prisoner";
                case SealedValueOneofCase.ExilePrisonerQuest: return "Exile Prisoner";
                case SealedValueOneofCase.ExecutePrisonerQuest: return "Execute Prisoner";
            }

            throw new ArgumentException($"unknown quest {quest}");
        }

        public static string MonthString(int month) {
            return new DateTime(777, month, 1).ToString("MMMM", CultureInfo.InvariantCulture);
        }

        private static string MonthString(Date date) {
            return new DateTime(date.Year, date.Month, 1)
                    .ToString("MMMM", CultureInfo.InvariantCulture);
        }

        public static string DateString(Date date) { return $"{MonthString(date)} {date.Year}"; }

        public static string UnaffiliatedHeroStatus(UnaffiliatedHeroType status) {
            switch (status) {
                case UnaffiliatedHeroType.UnaffiliatedHeroPrisoner: return "Prisoner";
                case UnaffiliatedHeroType.UnaffiliatedHeroMovingPrisoner: return "Moving Prisoner";
                case UnaffiliatedHeroType.UnaffiliatedHeroReturningPrisoner:
                    return "Returning Prisoner";
                case UnaffiliatedHeroType.UnaffiliatedHeroTraveler: return "Traveler";
                case UnaffiliatedHeroType.UnaffiliatedHeroResident: return "Resident";
                case UnaffiliatedHeroType.UnaffiliatedHeroOutlaw: return "Outlaw";

                case UnaffiliatedHeroType.UnaffiliatedHeroUnknown:
                default: throw new ArgumentException("Unknown free hero status");
            }
        }

        public static string ControlWeatherTypeName(ControlWeatherType type) {
            switch (type) {
                case ControlWeatherType.ControlWeatherStartBlizzard: return "Start Blizzard";

                case ControlWeatherType.ControlWeatherEndBlizzard: return "End Blizzard";

                case ControlWeatherType.ControlWeatherStartDrought: return "Start Drought";

                case ControlWeatherType.ControlWeatherEndDrought: return "End Drought";

                case ControlWeatherType.ControlWeatherUnknown:
                default: throw new ArgumentException("Unknown control weather type");
            }
        }

        public static string SiblingDescription(Gender gender) {
            switch (gender) {
                case Gender.Unknown: return "sibling";
                case Gender.Female: return "sister";
                case Gender.Male: return "brother";
                case Gender.Other: return "sibling";
                default: throw new ArgumentOutOfRangeException(nameof(gender), gender, null);
            }
        }

        public static string MaybeFactionLeaderDescriptionTemplate(
                FactionView faction,
                HeroView hero,
                IGameModel currentModel) {
            if (faction.FactionHeadId == hero.Id) {
                return "faction leader {HeroName}";
            } else if (faction.Leaders.Contains(hero.Id)) {
                return $"{FactionStringTemplate(faction, currentModel)}'s sworn {SiblingDescription(hero.PronounGender)} {{HeroName}}";
            } else {
                return $"{FactionStringTemplate(faction, currentModel)}'s hero {{HeroName}}";
            }
        }

        public static string Capitalized(string str) {
            if (String.IsNullOrEmpty(str)) return str;
            else if (str.Length == 1)
                return str.ToUpper();
            else
                return char.ToUpper(str[0]) + str[1..];
        }

        public static string ListString(IList<String> strings) {
            if (strings.Count == 1) {
                return strings[0];
            } else if (strings.Count == 2) {
                return $"{strings[0]} and {strings[1]}";
            } else {
                string str = "";
                for (int i = 0; i < strings.Count - 1; i++) { str += strings[i] + ", "; }
                str += "and " + strings[^1];

                return str;
            }
        }

        public static string BeastEffectString(BeastInfo beastInfo) {
            var list = new List<String>();
            if (beastInfo.EconomyDevastation > 0) { list.Add("disrupting trade"); }
            if (beastInfo.AgricultureDevastation > 0) {
                list.Add("destroying livestock and crops");
            }
            if (beastInfo.InfrastructureDevastation > 0) {
                list.Add("damaging our infrastructure");
            }

            return ListString(list);
        }

        private static string ConditionalFactionStringTemplate(
                FactionView faction,
                IGameModel gameModel,
                bool useFactionName) {
            if (useFactionName) return faction.Name;
            return "{FactionLeaderName}";
        }

        public static string FactionStringTemplate(FactionView faction, IGameModel gameModel) {
            return ConditionalFactionStringTemplate(faction, gameModel, DisplayFactionName);
        }

        public static string AlternateFactionStringTemplate(
                FactionView faction,
                IGameModel gameModel) {
            return ConditionalFactionStringTemplate(faction, gameModel, !DisplayFactionName);
        }

        public static string ResolvedFactionString(FactionView faction, IGameModel gameModel) {
            var template = FactionStringTemplate(faction, gameModel);
            if (template.Contains("{FactionLeaderName}")) {
                var hero = gameModel.Heroes[faction.FactionHeadId];
                var textEntry = ClientTextProvider.Provider.GetTextEntry(hero.NameTextId);
                if (textEntry != null && !string.IsNullOrEmpty(textEntry.Text)) {
                    return template.Replace("{FactionLeaderName}", textEntry.Text);
                } else {
                    return template.Replace("{FactionLeaderName}", "Leader");
                }
            }
            return template;
        }
    }
}