// Copyright (c) Strange Loop Games. All rights reserved.
// See LICENSE file in the project root for full license information.

namespace Eco.Mods.TechTree
{
    using Eco.Gameplay.EcopediaRoot;
    using Eco.Gameplay.Players;
    using Eco.Gameplay.Systems.TextLinks;
    using Eco.Gameplay.Utils;
    using Eco.Shared.Utils;
    using System.Collections.Generic;
    using System.Linq;
    using Eco.Gameplay.Civics;
    using System.Text;
    using Eco.Shared.Localization;
    using Eco.Gameplay.GameActions;
    using Eco.Gameplay.Economy;
    using Eco.Gameplay.Housing.PropertyValues;
    using Eco.Gameplay.Skills;
    using Eco.Gameplay.Systems.Tooltip;
    using Eco.Gameplay.Systems;
    using Eco.Core.Utils;
    using Eco.Core.Systems;
    using Eco.Gameplay.Civics.Misc;

    //Various classes that append dynamic data into Ecopedia pages.
    public class EcopediaConstitutionSettings : IEcopediaGeneratedData
    {
        public IEnumerable<EcopediaPageReference> PagesWeSupplyDataFor() => new EcopediaPageReference("CivicObjectComponent", "World Index", "Current Government", Localizer.DoStr("Current Government")).SingleItemAsEnumerable();

        public LocString GetEcopediaData(Player player, EcopediaPage page)
        {
            var sb = new LocStringBuilder();
            sb.AppendLine(TextLoc.HeaderLocStr("World Settings"));
            var valToOverthrow = Text.StyledNum(CivicsPlugin.Obj.Config.ValueAdditionToOverthrow);
            sb.AppendLineLoc($"Constitutions can be overthrown when their value is exceeded by {valToOverthrow}%.");
            sb.AppendLine();
            sb.AppendLine(CivicsUtils.AllActiveAndValid<Constitution>(null).MakeListLoc($"Current Constitutions"));
            return sb.ToLocString();
        }
    }

    //Various classes that append dynamic data into Ecopedia pages.
    public class EcopediaHousingData : IEcopediaGeneratedData
    {
        public IEnumerable<EcopediaPageReference> PagesWeSupplyDataFor() => new EcopediaPageReference(null, null, "Residency", Localizer.DoStr("Residency")).SingleItemAsEnumerable();

        public LocString GetEcopediaData(Player player, EcopediaPage page)
        {
            var penalties = HomePropertyValue.OccupancyPenalties;
            if (penalties == null) return LocString.Empty;
            List<string> list = new List<string>();
            for (int i = 1; i < penalties.Length; i++) list.Add($"{Localizer.Plural("Occupant", i - 1)}: {Text.StyledPercent(penalties[i])}");
            return list.MakeListLoc($"Occupancy Penalties:", false);
        }
    }

    
    //Various classes that append dynamic data into Ecopedia pages.
    public class EcopediaSkillData : IEcopediaGeneratedData
    {
        static EcopediaPageReference[] pages = new[] { new EcopediaPageReference(null, null, "Skills Overview", Localizer.DoStr("Skills Overview")),
                                                        new EcopediaPageReference(null, null, "Experience", Localizer.DoStr("Experience"))};
        public IEnumerable<EcopediaPageReference> PagesWeSupplyDataFor() => pages;

        public LocString GetEcopediaData(Player player, EcopediaPage page)
        {
            var sb = new LocStringBuilder();
            if (page.Name == "Skills Overview" && FeatureConfig.Obj.EducationEnabled)
            { 
                sb.AppendLine(TextLoc.HeaderLocStr($"World Skill Settings"));
                sb.AppendLineLoc($"Max Professions per Citizen: {(SkillManager.Obj.CurMaxProfessions != int.MaxValue ? Text.StyledInt(SkillManager.Obj.CurMaxProfessions) : TooltipUtil.None)}");
                sb.AppendLineLoc($"Max Specialties per Citizen: {(SkillManager.Obj.CurMaxSpecialties != int.MaxValue ? Text.StyledInt(SkillManager.Obj.CurMaxSpecialties) : TooltipUtil.None)}");
                if (SkillManager.Obj.CurMaxProfessions != int.MaxValue || SkillManager.Obj.CurMaxSpecialties != int.MaxValue)
                    sb.AppendLineLoc($"Over-Specialization Rate: {Text.StyledPercent(SkillManager.Obj.GetOverSpecializationRate())}");

                if (UserCountManager.Obj.TargetMaxUsers != 0) sb.AppendLineLoc($"Desired Max Users: {Text.InfoLight(UserCountManager.Obj.TargetMaxUsers)}");
                    sb.AppendLine(TextLoc.SubtextLocStr("0% means users get the bare-minimum number based on targeted number of players, each specialty going to each person once.  100% means everyone gets every specailty.").WrapParentheses());

                for(int i = 0; i < 5; i++)
                {
                    sb.AppendLine();
                    sb.AppendLine(TextLoc.BoldLocStr($"Tier {i+1} Skills"));
                    sb.AppendLine(ParamExplanation.DescribeType(typeof(SkillReqs), false, (prop) => prop.Name != nameof(SkillReqs.Tier) ,SkillManager.Obj.GetOrMakeReqs((float)i)));
                    sb.AppendLine(2);
                }
            }
            else
            {
                sb.AppendLine(TextLoc.HeaderLocStr("XP Needed For Each Star"));
                SkillManager.Obj.Settings.LevelUps.ForEachIndex((val,index) => sb.AppendLineLoc($"{Localizer.Ordinal(index + 1)} star: {Text.StyledInt(val)}"));
                sb.AppendLineLocStr($"Each additional star after these costs {Text.StyledPercent(SkillManager.Obj.Settings.LevelUpPostPercent)} more than the previous.");
            }
            return sb.ToLocString();
        }
    }


    //Various classes that append dynamic data into Ecopedia pages.
    public class EcopediaLawData : IEcopediaGeneratedData
    {
        public IEnumerable<EcopediaPageReference> PagesWeSupplyDataFor() => new EcopediaPageReference(null, "Government", "Laws", Localizer.DoStr("Laws")).SingleItemAsEnumerable();

        public LocString GetEcopediaData(Player player, EcopediaPage page)
        {
            var sb = new LocStringBuilder();
            sb.AppendLine(typeof(GameAction).DerivedTypes().Where(x=>!x.IsAbstract).OrderBy(x=>x.GetLocDisplayName()).Select(x=>x.UILink()).MakeListLoc($"Available Causes"));
            sb.AppendLine(typeof(LegalAction).DerivedTypes().Where(x=>!x.IsAbstract).OrderBy(x => x.GetLocDisplayName()).Select(x => x.UILink()).MakeListLoc($"Available Effects"));
            return sb.ToLocString();
        }
    }

    public class EcopediaReputationData : IEcopediaGeneratedData
    {
        public IEnumerable<EcopediaPageReference> PagesWeSupplyDataFor() => new EcopediaPageReference(null, null, "Reputation", Localizer.DoStr("Reputation")).SingleItemAsEnumerable();

        public LocString GetEcopediaData(Player player, EcopediaPage page)
        {
            var sb = new LocStringBuilder();
            sb.AppendLineLoc($"A citizen may grant reputation to others with a limit of {Text.StyledNum(Reputation.MaxGivableRep)} points (positive or negative) per day.");
            sb.AppendLine();
            var reps = UserManager.Config.Reputations.Select(x=>x.ToString());
            sb.AppendListLoc($"Reputation Titles", reps, false, false);
            return sb.ToLocString();
        }
    }
}
