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

namespace eagle {
    public class BattleProgressRowController : MonoBehaviour {
        public TMP_Text provinceLabel;
        public BattleThermometer thermometer;
        public TMP_Text outcomeLabel;
        public Button actionButton;
        public TMP_Text actionButtonLabel;

        public void Populate(
                ShardokBattleView battle,
                IGameModel model,
                Action<string> goToBattleAction,
                string fightableGameId) {
            // Province name
            if (model.Provinces.TryGetValue(battle.DefenderProvince, out var pv) &&
                model.PlayerId.HasValue) {
                provinceLabel.text = GUIUtils.DarkColoredProvinceName(pv, model.PlayerId.Value);
            } else if (pv != null) {
                provinceLabel.text = pv.Name;
            } else {
                provinceLabel.text = $"Province {battle.DefenderProvince}";
            }

            bool isSelf = battle.PlayerInfos.Any(pi => pi.Hostility == Hostility.SelfHostility);
            bool isAllied = isSelf ||
                            battle.PlayerInfos.Any(pi => pi.Hostility == Hostility.AlliedHostility);

            bool hasWinner = battle.WinningFactionId.HasValue;

            if (hasWinner) {
                thermometer.gameObject.SetActive(false);
                outcomeLabel.gameObject.SetActive(true);

                bool isAlliedWin = false;
                if (model.PlayerId.HasValue) {
                    var playerFaction = model.PlayerId.Value;
                    var winnerFaction = battle.WinningFactionId.Value;
                    isAlliedWin =
                            winnerFaction == playerFaction ||
                            (model.ActiveFactions.TryGetValue(winnerFaction, out var wf) &&
                             wf.FactionRelationships.Any(
                                     r => r.TargetFactionId == playerFaction &&
                                          r.RelationshipLevel == FactionRelationshipView.Types
                                                                         .RelationshipLevel.Ally));
                }

                outcomeLabel.text = isAllied && isAlliedWin ? "Victory!" : "Defeat!";
                outcomeLabel.color =
                        isAlliedWin ? new Color(0.2f, 0.8f, 0.2f) : new Color(0.8f, 0.2f, 0.2f);

                actionButton.gameObject.SetActive(false);
            } else {
                thermometer.gameObject.SetActive(true);
                outcomeLabel.gameObject.SetActive(false);

                Color defColor;
                IList<Color> atkColors;
                if (pv != null && pv.RulingFactionId.HasValue) {
                    int defFactionId = pv.RulingFactionId.Value;
                    defColor = PlayerColors.LightPlayerColor(defFactionId);
                    atkColors = battle.PlayerInfos.Where(pi => pi.EagleFactionId != defFactionId)
                                        .Select(pi => pi.EagleFactionId)
                                        .Distinct()
                                        .OrderBy(id => id)
                                        .Select(id => PlayerColors.LightPlayerColor(id))
                                        .ToList();
                    if (atkColors.Count == 0)
                        atkColors = new List<Color> { PlayerColors.LightPlayerColor(1) };
                } else {
                    defColor = PlayerColors.LightPlayerColor(0);
                    atkColors = new List<Color> { PlayerColors.LightPlayerColor(1) };
                }

                if (isAllied && battle.DefenderTroopCount.HasValue &&
                    battle.AttackerTroopCount.HasValue) {
                    thermometer.UpdateBalance(
                            battle.DefenderTroopCount.Value,
                            battle.AttackerTroopCount.Value,
                            defColor,
                            atkColors);
                } else {
                    thermometer.UpdateBalance(battle.DefenderRatio, defColor, atkColors);
                }

                actionButton.onClick.RemoveAllListeners();
                var gameId = battle.ShardokGameId;

                if (isSelf) {
                    bool isFightable = gameId == fightableGameId;
                    actionButton.gameObject.SetActive(true);
                    actionButton.interactable = isFightable;
                    actionButtonLabel.text = isFightable ? "Fight!" : "Waiting...";
                    if (isFightable) {
                        actionButton.onClick.AddListener(() => goToBattleAction?.Invoke(gameId));
                    }
                } else if (isAllied) {
                    actionButton.gameObject.SetActive(true);
                    actionButton.interactable = true;
                    actionButtonLabel.text = "Observe";
                    actionButton.onClick.AddListener(() => goToBattleAction?.Invoke(gameId));
                } else {
                    actionButton.gameObject.SetActive(false);
                }
            }
        }
    }
}
