using System;
using System.Linq;
using EagleGUIUtils;
using Net.Eagle0.Eagle.Common;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;

namespace eagle {
    using ProvinceId = Int32;

    public class DominionTableRowController : TableRowController,
                                              IPointerEnterHandler,
                                              IPointerExitHandler,
                                              IPointerClickHandler,
                                              System.IDisposable {
        public TMP_Text provinceName;
        public TMP_Text ruler;
        public TMP_Text support;
        public TMP_Text commanderCount;
        public TMP_Text battalionCount;
        public TMP_Text troopCount;
        public TMP_Text economy;
        public TMP_Text agriculture;
        public TMP_Text infrastructure;
        public TMP_Text gold;
        public TMP_Text food;
        public TMP_Text freeHeroes;
        public TMP_Text castles;
        public GameObject beasts;
        public GameObject drought;
        public GameObject blizzard;
        public GameObject epidemic;
        public GameObject festival;
        public GameObject flood;

        private ProvinceId ProvinceId;
        private DynamicHeroTextUpdater textUpdater = new DynamicHeroTextUpdater();

        private void SetDevastatedValue(TMP_Text textField, float baseValue, float devastation) {
            if (devastation == 0.0f) {
                textField.color = Color.black;
                textField.text = ProvinceStatUtils.RoundedStat(baseValue).ToString();
            } else {
                textField.color = Color.red;
                var devastatedValue = Math.Max(0.0f, baseValue - devastation);
                textField.text = ProvinceStatUtils.RoundedStat(devastatedValue).ToString();
            }
        }

        public void
        Set(ProvinceId provinceId, IGameModel model, bool isSelected, bool hasCommands) {
            ProvinceId = provinceId;

            var province = model.Provinces[provinceId];

            provinceName.text = province.Name;
            if (isSelected) {
                provinceName.color = Color.magenta;
            } else if (hasCommands) {
                provinceName.color = Color.blue;
            } else {
                provinceName.color = Color.black;
            }

            var rulingHero = model.Heroes[province.FullInfo.RulingHeroId.Value];
            textUpdater.SetHeroText(ruler, rulingHero.NameTextId, "Ruler");
            support.text = GUIUtils.ConditionString(province.FullInfo.Support);
            commanderCount.text = province.FullInfo.RulingFactionHeroIds.Count.ToString();
            battalionCount.text = province.FullInfo.Battalions.Count.ToString();
            troopCount.text = province.FullInfo.Battalions.Sum(x => x.Size).ToString();

            SetDevastatedValue(
                    economy,
                    province.FullInfo.Economy,
                    province.FullInfo.EconomyDevastation);
            SetDevastatedValue(
                    agriculture,
                    province.FullInfo.Agriculture,
                    province.FullInfo.AgricultureDevastation);
            SetDevastatedValue(
                    infrastructure,
                    province.FullInfo.Infrastructure,
                    province.FullInfo.InfrastructureDevastation);

            gold.text = province.FullInfo.Gold.ToString();
            food.text = province.FullInfo.Food.ToString();
            freeHeroes.text = province.FullInfo.UnaffiliatedHeroes.Count.ToString();
            castles.text = province.FullInfo.CastleCount.ToString();

            beasts.gameObject.SetActive(false);
            drought.gameObject.SetActive(false);
            blizzard.gameObject.SetActive(false);
            epidemic.gameObject.SetActive(false);
            festival.gameObject.SetActive(false);
            flood.gameObject.SetActive(false);

            foreach (var pe in province.KnownEvents) {
                switch (pe.SealedValueCase) {
                    case ProvinceEvent.SealedValueOneofCase.BeastsEvent:
                        var beastsEvent = pe.BeastsEvent;
                        var info = beastsEvent.BeastInfo;
                        var textField =
                                beasts.gameObject.GetComponentInParent<HoveringTooltipTextProvider>(
                                        includeInactive: true);
                        if (beastsEvent.Count == 1) {
                            var beastType = info.SingularName;
                            textField.text =
                                    $"A {beastType} is {DisplayNames.BeastEffectString(info)}!";
                        } else {
                            var beastType = info.PluralName;
                            textField.text =
                                    $"{beastsEvent.Count} {beastType} are {DisplayNames.BeastEffectString(info)}!";
                        }
                        beasts.gameObject.SetActive(true);
                        break;

                    case ProvinceEvent.SealedValueOneofCase.BlizzardEvent:
                        blizzard.gameObject.SetActive(true);
                        break;

                    case ProvinceEvent.SealedValueOneofCase.FestivalEvent:
                        festival.gameObject.SetActive(true);
                        break;

                    case ProvinceEvent.SealedValueOneofCase.FloodEvent:
                        flood.gameObject.SetActive(true);
                        break;

                    case ProvinceEvent.SealedValueOneofCase.DroughtEvent:
                        drought.gameObject.SetActive(true);
                        break;

                    case ProvinceEvent.SealedValueOneofCase.EpidemicEvent:
                        epidemic.gameObject.SetActive(true);
                        break;
                }
            }
        }

        // Start is called before the first frame update
        void Start() {}

        // Update is called once per frame
        void Update() {}

        public void Clicked() {}

        public void OnPointerEnter(PointerEventData eventData) {
            ShadeOn();
            GetComponentInParent<DominionPanelController>().RowHovered(ProvinceId);
        }

        public void OnPointerExit(PointerEventData eventData) {
            ShadeOff();
            GetComponentInParent<DominionPanelController>().RowUnhovered();
        }

        public void OnPointerClick(PointerEventData eventData) {
            GetComponentInParent<DominionPanelController>().RowClicked(ProvinceId);
        }

        public void Dispose() { textUpdater?.Dispose(); }

        private void OnDestroy() { Dispose(); }
    }
}