using System;
using System.Collections.Generic;
using System.Linq;
using Net.Eagle0.Eagle.Api;
using Net.Eagle0.Eagle.Api.Command.Util;

namespace eagle {
    using ProvinceId = Int32;

    public class PleaseRecruitMeCommandSelector : PopupPanelController {
        private List<GeneratedTextListener> heroNameListeners = new();
        private List<string> cachedHeroNames = new();
        struct HeroInfo {
            public ProvinceId provinceId;
            public ExpandedUnaffiliatedHero hero;
        }

        public HeroDetailsController heroDetailsController;

        public Action<SelectedCommand> submissionAction;

        public IGameModel Model { get; set; }

        public int CommandIndex { get; set; }
        private AvailableCommand _availableCommand = null;
        public AvailableCommand AvailableCommand {
            get => _availableCommand;
            set {
                _availableCommand = value;
                if (value == null) {
                    ClearHeroNameListeners();
                    _offers = new List<HeroInfo>();
                    PopupInfos = new List<PopupInfo>();
                } else {
                    ClearHeroNameListeners();
                    _offers = _availableCommand.PleaseRecruitMeCommand.AvailableProvinces
                                      .SelectMany(
                                              p => p.AvailableHeroes.Select(
                                                      h => new HeroInfo {
                                                          provinceId = p.ProvinceId,
                                                          hero = h
                                                      }))
                                      .ToList();

                    // Initialize cached hero names and set up listeners
                    cachedHeroNames = new List<string>(new string[_offers.Count]);
                    SetupHeroNameListeners();

                    PopupInfos = _offers.Select((heroInfo, index) => new PopupInfo {
                                            titleText = "Please Recruit Me!",
                                            mainText = GetHeroMainText(index, heroInfo.provinceId),
                                            mainTextLlmId = heroInfo.hero.PleaseRecruitMeTextId,
                                            affectedProvinceIds =
                                                    new List<ProvinceId>(heroInfo.provinceId)
                                        })
                                         .ToList();

                    SetUpPanel();
                }
            }
        }

        private List<HeroInfo> _offers = new List<HeroInfo>();

        private void ClearHeroNameListeners() {
            foreach (var listener in heroNameListeners) {
                ClientTextProvider.Provider.RemoveListener(listener);
            }
            heroNameListeners.Clear();
        }

        private void SetupHeroNameListeners() {
            for (int i = 0; i < _offers.Count; i++) {
                var heroInfo = _offers[i];
                if (!string.IsNullOrEmpty(heroInfo.hero.Hero.NameTextId)) {
                    var listener = new GeneratedTextListener(
                            heroInfo.hero.Hero.NameTextId,
                            "",
                            "",
                            i,
                            (index, text) => {
                                if (index < cachedHeroNames.Count) {
                                    cachedHeroNames[index] = text;
                                    UpdatePopupInfoMainText(index);
                                }
                            });

                    heroNameListeners.Add(listener);
                    ClientTextProvider.Provider.AddListener(listener);
                }
            }
        }

        private string GetHeroMainText(int index, ProvinceId provinceId) {
            var heroName = !string.IsNullOrEmpty(cachedHeroNames[index]) ? cachedHeroNames[index]
                                                                         : "A hero";
            return $"{heroName} wishes to join us in {Model.Provinces[provinceId].Name}.\n\n";
        }

        private void UpdatePopupInfoMainText(int index) {
            if (index < PopupInfos.Count && index < _offers.Count) {
                var heroInfo = _offers[index];
                PopupInfos[index] = new PopupInfo {
                    titleText = "Please Recruit Me!",
                    mainText = GetHeroMainText(index, heroInfo.provinceId),
                    mainTextLlmId = heroInfo.hero.PleaseRecruitMeTextId,
                    affectedProvinceIds = new List<ProvinceId>(heroInfo.provinceId)
                };
            }
        }

        private SelectedCommand SelectedCommand(bool accept) {
            return new SelectedCommand {
                PleaseRecruitMeCommand =
                        new PleaseRecruitMeSelectedCommand {
                            ProvinceId = _offers[DisplayedIndex].provinceId,
                            HeroId = _offers[DisplayedIndex].hero.Hero.Id,
                            Accept = accept
                        }
            };
        }

        public void AcceptButtonClicked() {
            submissionAction(SelectedCommand(true));
            AvailableCommand = null;
            SetUpPanel();
        }

        public void RejectButtonClicked() {
            submissionAction(SelectedCommand(false));
            AvailableCommand = null;
            SetUpPanel();
        }

        protected override void SetUpPanel() {
            base.SetUpPanel();

            if (_offers.Count > DisplayedIndex) {
                heroDetailsController.SetHero(_offers[DisplayedIndex].hero.Hero, Model);
            }
        }

        void OnDestroy() { ClearHeroNameListeners(); }
    }
}