using System;
using System.Collections.Generic;
using common;
using Net.Eagle0.Common;
using Net.Eagle0.Eagle.Api;
using Net.Eagle0.Eagle.Api.Command.Util;
using Net.Eagle0.Eagle.Common;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

// ReSharper disable once CheckNamespace
namespace eagle {
    using ProvinceId = Int32;

    public class AttackDecisionCommandSelector : CommandSelector {
        public EventBasedTable unitsTable;
        public EventBasedTable armiesTable;

        private static readonly Dictionary<AttackDecisionType.SealedValueOneofCase, string>
                CommitStrings = new() {
                    { AttackDecisionType.SealedValueOneofCase.Advance, "Commit Advance" },
                    { AttackDecisionType.SealedValueOneofCase.DemandTribute,
                      "Commit Demand Tribute" },
                    { AttackDecisionType.SealedValueOneofCase.Withdraw, "Commit Withdraw" },
                    { AttackDecisionType.SealedValueOneofCase.SafePassage, "Commit Safe Travel" }
                };

        public override AvailableCommand.SealedValueOneofCase CommandType =>
                AvailableCommand.SealedValueOneofCase.AttackDecisionCommand;
        public override string HeaderString => "Attack Decision";
        public override string CommitButtonString =>
                CommitStrings[SelectedDecision.SealedValueCase];
        public override bool EnableCommitButton =>
                SelectedDecision.SealedValueCase !=
                        AttackDecisionType.SealedValueOneofCase.DemandTribute ||
                FoodDemanded > 0 || GoldDemanded > 0;
        public override string DisabledCommitButtonReason =>
                "Must select some food or gold for tribute";

        public override List<ProvinceId> TargetedProvinces =>
                new() { AttackDecisionCommand.ActingProvinceId };

        public Toggle advanceToggle;
        public Toggle demandTributeToggle;
        public Toggle withdrawToggle;
        public Toggle safePassageToggle;

        public GameObject advanceImage;
        public GameObject demandTributeImage;
        public GameObject withdrawImage;
        public GameObject safePassageImage;

        public Image goldIcon;
        public Image foodIcon;
        public Slider goldSlider;
        public Slider foodSlider;
        public TMP_Text goldLabel;
        public TMP_Text foodLabel;

        private AttackDecisionAvailableCommand AttackDecisionCommand =>
                _availableCommand.AttackDecisionCommand;

        private AttackDecisionType SelectedDecision {
            get {
                if (advanceToggle.isOn)
                    return new AttackDecisionType { Advance = new AdvanceDecision() };
                if (demandTributeToggle.isOn)
                    return new AttackDecisionType {
                        DemandTribute = new DemandTributeDecision { Tribute = Tribute }
                    };
                if (withdrawToggle.isOn)
                    return new AttackDecisionType { Withdraw = new WithdrawDecision() };
                if (safePassageToggle.isOn)
                    return new AttackDecisionType { SafePassage = new SafePassageDecision() };

                throw new Exception("No decision selected");
            }
        }

        private int FoodDemanded => (int)foodSlider.value;
        private int GoldDemanded => (int)goldSlider.value;

        private TributeAmount Tribute =>
                demandTributeToggle.isOn
                        ? new TributeAmount { Food = FoodDemanded, Gold = GoldDemanded }
                        : null;

        public override SelectedCommand Command => new() {
            AttackDecisionCommand =
                    new AttackDecisionSelectedCommand { Decision = SelectedDecision }
        };

        protected override void SetUpUI() {
            unitsTable.RowCount = AttackDecisionCommand.ActingUnits.Count;

            AttackDecisionCommand.ActingUnits.Each((cu, idx) => {
                CombatUnitRowController row = unitsTable.ComponentAt<CombatUnitRowController>(idx);
                row.Hero = cu.Hero;
                row.Battalion = cu.Battalion;
            });

            armiesTable.RowCount = AttackDecisionCommand.Armies.Count;
            AttackDecisionCommand.Armies.Each((army, idx) => {
                IncomingArmyTableRow row = armiesTable.ComponentAt<IncomingArmyTableRow>(idx);
                row.Faction = _model.FactionName(army.FactionId);
                row.HeroCount = army.HeroCount;
                row.TroopCount = army.TroopCount;
                switch (army.Hostility) {
                    case Hostility.AlliedHostility: row.TextColor = Color.green; break;
                    case Hostility.SelfHostility: row.TextColor = Color.blue; break;
                    case Hostility.EnemyHostility: row.TextColor = Color.red; break;
                }
                row.Origin = _model.Provinces[army.OriginProvinceId].Name;
            });

            bool enableAttack = false;
            bool enableWithdraw = false;
            bool enableDemandTribute = false;
            bool enableSafePassage = false;
            var maxGoldTribute = 0;
            var maxFoodTribute = 0;

            foreach (var ad in AttackDecisionCommand.AvailableDecisions) {
                switch (ad.SealedValueCase) {
                    case AttackDecisionType.SealedValueOneofCase.Advance:
                        enableAttack = true;
                        break;
                    case AttackDecisionType.SealedValueOneofCase.Withdraw:
                        enableWithdraw = true;
                        break;
                    case AttackDecisionType.SealedValueOneofCase.DemandTribute:
                        enableDemandTribute = true;
                        maxGoldTribute = ad.DemandTribute.Tribute.Gold;
                        maxFoodTribute = ad.DemandTribute.Tribute.Food;
                        break;
                    case AttackDecisionType.SealedValueOneofCase.SafePassage:
                        enableSafePassage = true;
                        break;
                }
            }

            advanceToggle.enabled = enableAttack;
            advanceToggle.gameObject.SetActive(enableAttack);
            advanceImage.SetActive(enableAttack);

            withdrawToggle.enabled = enableWithdraw;
            withdrawToggle.gameObject.SetActive(enableWithdraw);
            withdrawImage.SetActive(enableWithdraw);

            demandTributeToggle.enabled = enableDemandTribute;
            demandTributeToggle.gameObject.SetActive(enableDemandTribute);
            demandTributeImage.SetActive(enableDemandTribute);

            safePassageToggle.enabled = enableSafePassage;
            safePassageToggle.gameObject.SetActive(enableSafePassage);
            safePassageImage.SetActive(enableSafePassage);

            goldSlider.minValue = 0;
            goldSlider.maxValue = maxGoldTribute;
            foodSlider.minValue = 0;
            foodSlider.maxValue = maxFoodTribute;

            // ReSharper disable once PossibleLossOfFraction
            goldSlider.value = maxGoldTribute / 2;
            goldLabel.text = ((int)(goldSlider.value)).ToString();

            // ReSharper disable once PossibleLossOfFraction
            foodSlider.value = maxFoodTribute / 2;
            foodLabel.text = ((int)(foodSlider.value)).ToString();

            if (enableAttack) {
                withdrawToggle.SetIsOnWithoutNotify(false);
                demandTributeToggle.SetIsOnWithoutNotify(false);
                safePassageToggle.SetIsOnWithoutNotify(false);
                advanceToggle.isOn = true;
            } else if (enableWithdraw) {
                advanceToggle.SetIsOnWithoutNotify(false);
                demandTributeToggle.SetIsOnWithoutNotify(false);
                safePassageToggle.SetIsOnWithoutNotify(false);
                withdrawToggle.isOn = true;
            } else if (enableDemandTribute) {
                advanceToggle.SetIsOnWithoutNotify(false);
                withdrawToggle.SetIsOnWithoutNotify(false);
                safePassageToggle.SetIsOnWithoutNotify(false);
                demandTributeToggle.isOn = true;
            } else if (enableSafePassage) {
                advanceToggle.SetIsOnWithoutNotify(false);
                withdrawToggle.SetIsOnWithoutNotify(false);
                demandTributeToggle.SetIsOnWithoutNotify(false);
                safePassageToggle.isOn = true;
            }

            EnableSliders(false);
        }

        public void GoldSliderChanged(float newValue) {
            goldLabel.text = ((int)newValue).ToString();
        }

        public void FoodSliderChanged(float newValue) {
            foodLabel.text = ((int)newValue).ToString();
        }

        private void EnableSliders(bool newEnabled) {
            goldIcon.gameObject.SetActive(newEnabled);
            foodIcon.gameObject.SetActive(newEnabled);
            goldSlider.gameObject.SetActive(newEnabled);
            foodSlider.gameObject.SetActive(newEnabled);
            goldLabel.gameObject.SetActive(newEnabled);
            foodLabel.gameObject.SetActive(newEnabled);
        }

        public void ToggleChanged(bool value) {
            bool enableSliders =
                    (SelectedDecision.SealedValueCase ==
                     AttackDecisionType.SealedValueOneofCase.DemandTribute);

            EnableSliders(enableSliders);
        }
    }
}
