using System;
using System.Collections.Generic;
using System.Linq;
using EagleGUIUtils;
using Net.Eagle0.Eagle.Api;
using Net.Eagle0.Eagle.Common;
using Net.Eagle0.Eagle.Views;
using TMPro;
using UnityEngine.UI;

namespace eagle {
    using ProvinceId = Int32;
    using HeroId = Int32;

    public class ImproveCommandSelector : CommandSelector {
        public HeroDropdownController heroDropdownController;
        public TMP_Dropdown typeDropdown;
        public Toggle lockToggle;

        List<HeroView> orderedHeroes;

        private int SelectedTypeIndex => typeDropdown.value;
        private ImproveAvailableCommand ImproveAvailableCommand => _availableCommand.ImproveCommand;
        private ProvinceId ActingProvinceId => ImproveAvailableCommand.ActingProvinceId;
        private ImprovementType SelectedType =>
                ImproveAvailableCommand.AvailableTypes[SelectedTypeIndex];

        private float OriginalImprovementValueForType(ImprovementType type) {
            var province = _model.Provinces[ActingProvinceId];
            switch (type) {
                case ImprovementType.Agriculture: return province.FullInfo.Agriculture;
                case ImprovementType.Economy: return province.FullInfo.Economy;
                case ImprovementType.Infrastructure: return province.FullInfo.Infrastructure;
                case ImprovementType.Devastation:
                    return province.FullInfo.EconomyDevastation +
                           province.FullInfo.AgricultureDevastation +
                           province.FullInfo.InfrastructureDevastation;
                default: throw new InvalidOperationException($"unknown type {type}");
            }
        }

        private float EffectiveImprovementValueForType(ImprovementType type) {
            var province = _model.Provinces[ActingProvinceId];
            switch (type) {
                case ImprovementType.Agriculture:
                    return province.FullInfo.Agriculture - province.FullInfo.AgricultureDevastation;
                case ImprovementType.Economy:
                    return province.FullInfo.Economy - province.FullInfo.EconomyDevastation;
                case ImprovementType.Infrastructure:
                    return province.FullInfo.Infrastructure -
                           province.FullInfo.InfrastructureDevastation;
                case ImprovementType.Devastation:
                    return province.FullInfo.EconomyDevastation +
                           province.FullInfo.AgricultureDevastation +
                           province.FullInfo.InfrastructureDevastation;
                default: throw new InvalidOperationException($"unknown type {type}");
            }
        }

        private int MinimumImprovementIndex(ProvinceView province) {
            var minIndex = 0;
            float minValue =
                    OriginalImprovementValueForType(ImproveAvailableCommand.AvailableTypes[0]);
            for (int i = 1; i < ImproveAvailableCommand.AvailableTypes.Count; i++) {
                float thisVal =
                        OriginalImprovementValueForType(ImproveAvailableCommand.AvailableTypes[i]);
                if (thisVal < minValue) {
                    minIndex = i;
                    minValue = thisVal;
                }
            }
            return minIndex;
        }

        private void ChooseDefaultImprovement(ProvinceView province) {
            var devastationIndex =
                    ImproveAvailableCommand.AvailableTypes.IndexOf(ImprovementType.Devastation);
            if (devastationIndex == -1) {
                typeDropdown.value = MinimumImprovementIndex(province);
            } else {
                typeDropdown.value = devastationIndex;
            }
        }

        protected override void SetUpUI() {
            var province = _model.Provinces[ImproveAvailableCommand.ActingProvinceId];
            var improveCommand = ImproveAvailableCommand;

            typeDropdown.ClearOptions();

            orderedHeroes = ImproveAvailableCommand.AvailableHeroIds.Select(id => _model.Heroes[id])
                                    .ToList();
            heroDropdownController.AvailableHeroes = orderedHeroes;

            heroDropdownController.SelectedHeroId = improveCommand.RecommendedHeroId;

            typeDropdown.AddOptions(
                    improveCommand.AvailableTypes.Select(DropdownStringForType).ToList());

            if (improveCommand.LockedType != ImprovementType.None) {
                var lockedType = improveCommand.LockedType;
                var lockedTypeIndex = improveCommand.AvailableTypes.IndexOf(lockedType);
                if (lockedTypeIndex > -1) {
                    typeDropdown.value = lockedTypeIndex;
                    lockToggle.isOn = true;
                } else {
                    ChooseDefaultImprovement(province);
                    lockToggle.isOn = false;
                }
            } else {
                ChooseDefaultImprovement(province);
                lockToggle.isOn = false;
            }
        }

        public override AvailableCommand.SealedValueOneofCase CommandType =>
                AvailableCommand.SealedValueOneofCase.ImproveCommand;
        public override string HeaderString => "Improve Province";
        public override string CommitButtonString => "Commit Improvement";

        public override List<HeroId> TargetedHeroIds =>
                new() { heroDropdownController.SelectedHeroId };
        public override bool HeroIsTargetable(HeroId heroId) {
            var index = orderedHeroes.FindIndex(h => h.Id == heroId);
            return index != -1;
        }

        public override void AddTargetedHero(int heroId) {
            heroDropdownController.SelectedHeroId = heroId;
        }

        public override SelectedCommand Command => new SelectedCommand {
            ImproveCommand =
                    new ImproveSelectedCommand {
                        ImprovementType = SelectedType,
                        ActingHeroId = heroDropdownController.SelectedHeroId,
                        LockType = lockToggle.isOn
                    }
        };

        private string DropdownStringForType(ImprovementType type) {
            var originalStat =
                    type == ImprovementType.Devastation
                            ? ProvinceStatUtils.RoundedDevastation(
                                      OriginalImprovementValueForType(type))
                            : ProvinceStatUtils.RoundedStat(OriginalImprovementValueForType(type));
            if (type == ImprovementType.Devastation) {
                return $"{type} ({GUIUtils.ColoredString(UnityEngine.Color.red, originalStat.ToString())})";
            }
            var devastatedStat =
                    ProvinceStatUtils.RoundedStat(EffectiveImprovementValueForType(type));
            if (devastatedStat == originalStat) {
                return $"{type} ({devastatedStat})";
            } else {
                return $"{type} ({GUIUtils.ColoredString(UnityEngine.Color.red, devastatedStat.ToString())} / {originalStat})";
            }
        }
    }
}