using System;
using Net.Eagle0.Eagle.Api;
using Net.Eagle0.Eagle.Api.Command.Util;
using Net.Eagle0.Eagle.Views;
using UnityEngine;
using UnityEngine.UI;

namespace eagle {
    using ProvinceId = Int32;

    public class HandleCapturedHeroesCommandSelector : CommandSelector {
        // Unity accessors
        public Toggle RecruitToggle;
        public Toggle ImprisonToggle;
        public Toggle ExileToggle;
        public Toggle ExecuteToggle;
        public Toggle ReturnToggle;

        public RawImage RecruitIcon;
        public RawImage ImprisonIcon;
        public RawImage ExileIcon;
        public RawImage ExecuteIcon;
        public RawImage ReturnIcon;

        public HeroDetailsController heroDetails;

        public GeneratedTextUpdater messageUpdater;

        public Button NextHeroButton;

        public HeroView SelectedHero => SelectedHeroWithOptions.Hero;

        public override AvailableCommand.SealedValueOneofCase CommandType =>
                AvailableCommand.SealedValueOneofCase.HandleCapturedHeroCommand;
        public override string HeaderString => "Handle Captured Hero";
        public override string CommitButtonString =>
                $"Commit {DisplayNames.CapturedHeroOptionNames[SelectedOption]}";

        private int _selectedHeroIndex;
        private ExpandedCapturedHero SelectedHeroWithOptions =>
                HandleCapturedHeroCommand.AvailableHeroes[_selectedHeroIndex];

        private HandleCapturedHeroAvailableCommand HandleCapturedHeroCommand =>
                _availableCommand.HandleCapturedHeroCommand;
        private ProvinceId ActingProvinceId => HandleCapturedHeroCommand.ActingProvinceId;

        public override bool WarnOnCommitButton =>
                SelectedOption == CapturedHeroOption.ReturnCapturedHeroOption;
        public override string CommitWarningText =>
                $"This will create a treaty with {_model.FactionName(SelectedHero.FactionId.Value)}";

        private CapturedHeroOption SelectedOption {
            get {
                if (RecruitToggle.isOn) return CapturedHeroOption.RecruitCapturedHeroOption;
                else if (ImprisonToggle.isOn)
                    return CapturedHeroOption.ImprisonCapturedHeroOption;
                else if (ExileToggle.isOn)
                    return CapturedHeroOption.ExileCapturedHeroOption;
                else if (ExecuteToggle.isOn)
                    return CapturedHeroOption.ExecuteCapturedHeroOption;
                else if (ReturnToggle.isOn)
                    return CapturedHeroOption.ReturnCapturedHeroOption;
                else
                    throw new ArgumentOutOfRangeException("Unknown captured hero option");
            }
        }

        protected override void SetUpUI() {
            if (_selectedHeroIndex >= HandleCapturedHeroCommand.AvailableHeroes.Count)
                _selectedHeroIndex = 0;
            NextHeroButton.gameObject.SetActive(
                    HandleCapturedHeroCommand.AvailableHeroes.Count > 1);
            DisplaySelectedHero();
        }

        public override SelectedCommand Command => new SelectedCommand {
            HandleCapturedHeroCommand =
                    new HandleCapturedHeroSelectedCommand() {
                        HeroId = SelectedHero.Id,
                        SelectedOption = SelectedOption
                    }
        };

        public void NextHeroButtonClicked() {
            _selectedHeroIndex++;
            if (_selectedHeroIndex >= HandleCapturedHeroCommand.AvailableHeroes.Count) {
                _selectedHeroIndex = 0;
            }

            DisplaySelectedHero();
        }

        private void DisplaySelectedHero() {
            heroDetails.SetHero(SelectedHero, _model);

            messageUpdater.TextId = SelectedHeroWithOptions.MessageId;

            // The order here is important: the last available toggle in this list
            // will be on by default
            ConditionallyEnable(
                    ExecuteToggle,
                    ExecuteIcon,
                    CapturedHeroOption.ExecuteCapturedHeroOption);
            ConditionallyEnable(ExileToggle, ExileIcon, CapturedHeroOption.ExileCapturedHeroOption);
            ConditionallyEnable(
                    ReturnToggle,
                    ReturnIcon,
                    CapturedHeroOption.ReturnCapturedHeroOption);
            ConditionallyEnable(
                    ImprisonToggle,
                    ImprisonIcon,
                    CapturedHeroOption.ImprisonCapturedHeroOption);
            ConditionallyEnable(
                    RecruitToggle,
                    RecruitIcon,
                    CapturedHeroOption.RecruitCapturedHeroOption);
        }

        private bool ConditionallyEnable(Toggle toggle, CapturedHeroOption option) {
            bool enable = SelectedHeroWithOptions.Options.Contains(option);
            toggle.gameObject.SetActive(enable);

            if (enable) {
                ExecuteToggle.isOn = false;
                ExileToggle.isOn = false;
                ImprisonToggle.isOn = false;
                RecruitToggle.isOn = false;
                ReturnToggle.isOn = false;

                toggle.isOn = true;
            } else
                toggle.isOn = false;

            return enable;
        }

        private void ConditionallyEnable(Toggle toggle, RawImage img, CapturedHeroOption option) {
            bool enable = ConditionallyEnable(toggle, option);

            Color color = img.color;
            color.a = enable ? 1.0f : 0.25f;
            img.color = color;
        }
    }
}
