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

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

    public class SendSuppliesCommandSelector : CommandSelector {
        private ProvinceId SelectedDestinationProvinceId =>
                SendSuppliesAvailableCommand.AvailableDestinationProvinceIds[ToDropdown.value];
        private ProvinceView SelectedDestinationProvince =>
                _model.Provinces[SelectedDestinationProvinceId];
        private HeroId SelectedActorId => heroDropdownController.SelectedHeroId;

        public TMP_Dropdown FromDropdown;
        public TMP_Dropdown ToDropdown;
        public Slider GoldSlider;
        public TMP_Text GoldTaken;
        public TMP_Text GoldLeft;
        public Slider FoodSlider;
        public TMP_Text FoodTaken;
        public TMP_Text FoodLeft;
        public HeroDropdownController heroDropdownController;

        public override AvailableCommand.SealedValueOneofCase CommandType =>
                AvailableCommand.SealedValueOneofCase.SendSuppliesCommand;
        public override string HeaderString => "Send Supplies";
        public override string CommitButtonString => "Commit Send";

        public override List<HeroId> TargetedHeroIds => new List<HeroId> { SelectedActorId };
        public override bool HeroIsTargetable(HeroId heroId) =>
                SendSuppliesAvailableCommand.AvailableHeroIds.Contains(heroId);
        public override void AddTargetedHero(HeroId heroId) =>
                heroDropdownController.SelectedHeroId = heroId;

        public override bool WarnOnCommitButton =>
                !SelectedDestinationProvince.RulingFactionId.HasValue ||
                SelectedDestinationProvince.RulingFactionId.Value != _model.PlayerId;
        public override string CommitWarningText =>
                $"You do not currently occupy {SelectedDestinationProvince.Name}. Are you sure you wish to send supplies there?";

        private SendSuppliesAvailableCommand SendSuppliesAvailableCommand =>
                _availableCommand.SendSuppliesCommand;
        private ProvinceId ActingProvinceId => SendSuppliesAvailableCommand.ActingProvinceId;

        protected override ProvinceId? TargetedProvince {
            get => SelectedDestinationProvinceId;

            set {
                if (value.HasValue) {
                    int index =
                            SendSuppliesAvailableCommand.AvailableDestinationProvinceIds.IndexOf(
                                    value.Value);
                    if (index != -1) ToDropdown.value = index;
                }
            }
        }

        public override bool EnableCommitButton => FoodSlider.value > 0 || GoldSlider.value > 0;
        public override string DisabledCommitButtonReason => "Must send some food or gold";

        protected override void SetUpUI() {
            FromDropdown.ClearOptions();
            FromDropdown.AddOptions(new List<String> { _model.Provinces[ActingProvinceId].Name });

            ToDropdown.ClearOptions();
            ToDropdown.AddOptions(SendSuppliesAvailableCommand.AvailableDestinationProvinceIds
                                          .Select(id => GUIUtils.DarkColoredProvinceName(
                                                          _model.Provinces[id],
                                                          _model.PlayerId.Value))
                                          .ToList());

            ToDropdown.value = 0;
            var firstOwned =
                    SendSuppliesAvailableCommand.AvailableDestinationProvinceIds.ToList().FindIndex(
                            pid => _model.Provinces[pid].RulingFactionId.HasValue &&
                                   _model.Provinces[pid].RulingFactionId.Value == _model.PlayerId);
            ToDropdown.value = firstOwned < 0 ? 0 : firstOwned;

            FoodSlider.value = 0;
            FoodSlider.minValue = 0;
            FoodSlider.maxValue = SendSuppliesAvailableCommand.FoodAvailable;
            FoodTaken.text = "0";
            FoodLeft.text = SendSuppliesAvailableCommand.FoodAvailable.ToString();

            GoldSlider.value = 0;
            GoldSlider.minValue = 0;
            GoldSlider.maxValue = SendSuppliesAvailableCommand.GoldAvailable;
            GoldTaken.text = "0";
            GoldLeft.text = SendSuppliesAvailableCommand.GoldAvailable.ToString();

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

        public override SelectedCommand Command => new SelectedCommand {
            SendSuppliesCommand =
                    new SendSuppliesSelectedCommand {
                        Food = (int)FoodSlider.value,
                        Gold = (int)GoldSlider.value,
                        ActingHeroId = SelectedActorId,
                        DestinationProvinceId = SelectedDestinationProvinceId,
                    }
        };

        public void FoodPlusClicked() {
            FoodSlider.value =
                    Math.Min(FoodSlider.maxValue, FoodSlider.value + KeyModifiedAmount.Amount());
        }

        public void FoodMinusClicked() {
            FoodSlider.value =
                    Math.Max(FoodSlider.minValue, FoodSlider.value - KeyModifiedAmount.Amount());
        }

        public void GoldPlusClicked() {
            GoldSlider.value =
                    Math.Min(GoldSlider.maxValue, GoldSlider.value + KeyModifiedAmount.Amount());
        }

        public void GoldMinusClicked() {
            GoldSlider.value =
                    Math.Max(GoldSlider.minValue, GoldSlider.value - KeyModifiedAmount.Amount());
        }

        // Add plus/minus clicks and label changes
        public void GoldSliderChanged(float newValue) {
            GoldTaken.text = newValue.ToString();
            GoldLeft.text = (SendSuppliesAvailableCommand.GoldAvailable - newValue).ToString();
        }

        public void FoodSliderChanged(float newValue) {
            FoodTaken.text = newValue.ToString();
            FoodLeft.text = (SendSuppliesAvailableCommand.FoodAvailable - newValue).ToString();
        }
    }
}
