using System.Collections.Generic;
using System.Linq;
using common;
using Eagle0.Tutorial;
using Net.Eagle0.Eagle.Views;
using UnityEngine;

namespace eagle {
    public class FreeHeroesTableController : MonoBehaviour {
        public GameObject panel;

        [Header("Hero Backstory Popup")]
        public GameObject popupPanel;
        public HeroDetailsController popupPanelDetailsController;
        public GeneratedTextUpdater popupPanelBackstory;

        private ProvinceView _currentProvince;
        public ProvinceView CurrentProvince {
            get => _currentProvince;
            set {
                if (_currentProvince != value) {
                    _currentProvince = value;
                    UpdateTables();
                }
            }
        }

        private IGameModel _model;
        public IGameModel Model { private
            get => _model;
            set {
                _model = value;
                UpdateTables();
                panel.SetActive(value != null);
            }
        }

        public EventBasedTable unaffiliatedHeroesTable;

        public CommandPanelController commandPanelController;

        private CommandSelector CommandSelector =>
                commandPanelController == null ? null : commandPanelController.Selector;

        public void UpdateTables() {
            if (Model == null) {
                panel.SetActive(false);
                return;
            }
            panel.SetActive(true);
            setUpUnaffiliatedHeroesTable();
        }

        private void SetUnaffiliatedHeroRowSelections(
                UnaffiliatedHeroRowController row,
                UnaffiliatedHeroBasics uh) {
            if (CommandSelector == null) {
                row.Selected = false;
                row.Selectable = false;
                row.RightSelectable = false;
            } else {
                row.Selected = commandPanelController.Selector.TargetedHeroIds.Contains(uh.HeroId);
                row.Selectable = commandPanelController.Selector.HeroIsTargetable(uh.HeroId);
                row.RightSelectable = false;
            }
        }

        public void UpdateUnaffiliatedHeroSelections() {
            if (UnaffiliatedHeroCount != unaffiliatedHeroesTable.RowCount) {
                setUpUnaffiliatedHeroesTable();
                return;
            }
            UnaffiliatedHeroes.Each(
                    (uh, i) => SetUnaffiliatedHeroRowSelections(
                            unaffiliatedHeroesTable.ComponentAt<UnaffiliatedHeroRowController>(i),
                            uh));
        }

        public void UnaffiliatedHeroRowClicked(int index) {
            var heroId = UnaffiliatedHeroes.ElementAt(index).HeroId;
            if (CommandSelector != null) { CommandSelector.AddTargetedHero(heroId); }
            UpdateUnaffiliatedHeroSelections();
        }

        public void LongHoverRowChanged(int? newIndex) {
            if (popupPanel == null) return;

            if (newIndex is {} index) {
                var heroId = UnaffiliatedHeroes.ElementAt(index).HeroId;
                if (Model.Heroes.TryGetValue(heroId, out var hero)) {
                    popupPanelDetailsController.SetHero(hero, Model);
                    popupPanelBackstory.TextId = hero.BackstoryTextId;
                    popupPanel.SetActive(true);
                }
            } else {
                popupPanel.SetActive(false);
            }
        }

        private void setUpUnaffiliatedHeroesTable() {
            unaffiliatedHeroesTable.RowCount = UnaffiliatedHeroCount;

            UnaffiliatedHeroes.Each((uh, i) => {
                var newRow = unaffiliatedHeroesTable.ComponentAt<UnaffiliatedHeroRowController>(i);
                newRow.SetUnaffiliatedHero(uh, Model);
                SetUnaffiliatedHeroRowSelections(newRow, uh);

                // Check if this hero's profession should trigger a tutorial
                if (Model.Heroes.TryGetValue(uh.HeroId, out var hero)) {
                    TutorialManager.Instance?.TriggerRegistry?.CheckProfessionTutorial(hero);
                }
            });
        }

        void Start() {
            panel.SetActive(Model != null);
            if (popupPanel != null) {
                PopupClipper.Ensure(popupPanel);
                popupPanel.SetActive(false);
            }
        }

        private bool HasProvinceInfo =>
                (CurrentProvince != null && CurrentProvince.FullInfo != null);

        private int UnaffiliatedHeroCount =>
                HasProvinceInfo ? CurrentProvince.FullInfo.UnaffiliatedHeroes.Count : 0;
        private List<UnaffiliatedHeroBasics> UnaffiliatedHeroes =>
                HasProvinceInfo ? CurrentProvince.FullInfo.UnaffiliatedHeroes
                                          .OrderByDescending(
                                                  uh => Model.Heroes[uh.HeroId],
                                                  HeroComparer.Shared)
                                          .ToList()
                                : new List<UnaffiliatedHeroBasics>();
    }
}