using System.Collections.Generic;
using System.Linq;
using common;
using Net.Eagle0.Eagle.Views;
using UnityEngine;
using FactionId = System.Int32;
using ProvinceId = System.Int32;

namespace eagle {
    public class MovingArmiesTableController : MonoBehaviour {
        public GameObject panel;

        public GameObject movingArmyPopupPanel;
        public EventBasedTable movingArmyPopupTable;

        private ProvinceView _currentProvince;
        public ProvinceView CurrentProvince {
            get => _currentProvince;
            set {
                if (_currentProvince != value) {
                    _currentProvince = value;
                    UpdateTables();
                }
            }
        }

        public void MovingArmyLongHoverRowChanged(int? newIndex) {
            if (newIndex is {} index) {
                var movingArmy = MovingArmies.ElementAt(index);
                if (movingArmy.UnitDetails.Any()) {
                    movingArmyPopupTable.RowCount = movingArmy.UnitDetails.Count;
                    for (int i = 0; i < movingArmy.UnitDetails.Count; i++) {
                        var details = movingArmy.UnitDetails[i];
                        var row = movingArmyPopupTable.ComponentAt<MovingArmyPopupRowController>(i);
                        row.SetHeroText(Model.Heroes[details.HeroId].NameTextId, "Hero");

                        var battalion = details.Battalion;
                        if (battalion != null) {
                            row.BattalionImage.texture =
                                    GetComponentInParent<EagleCommonTextures>().BattalionType(
                                            details.Battalion.Type);
                            row.BattalionImage.gameObject.SetActive(true);
                            row.BattalionSize.text = details.Battalion.Size.ToString();
                            row.BattalionSize.gameObject.SetActive(true);
                        } else {
                            row.BattalionImage.gameObject.SetActive(false);
                            row.BattalionSize.gameObject.SetActive(false);
                        }
                        movingArmyPopupPanel.SetActive(true);
                    }
                } else {
                    movingArmyPopupPanel.SetActive(false);
                }
            } else {
                movingArmyPopupPanel.SetActive(false);
            }
        }

        public void MovingArmyHoverRowChanged(int? newIndex) {
            if (newIndex is {} index) {
                var movingArmy = MovingArmies.ElementAt(index);
                mapController.OverrideTargetedProvinces = new List<ProvinceId> {
                    movingArmy.OriginProvinceId,
                    movingArmy.DestinationProvinceId
                };
            } else {
                mapController.OverrideTargetedProvinces = new List<ProvinceId>();
            }
        }

        private IGameModel _model;
        public IGameModel Model { private
            get => _model;
            set {
                _model = value;
                UpdateTables();
                panel.SetActive(value != null);
            }
        }

        public EventBasedTable movingArmiesTable;

        public MapController mapController;

        public void UpdateTables() {
            if (Model == null) {
                panel.SetActive(false);
                return;
            }
            panel.SetActive(true);
            SetUpMovingArmiesTable();
        }

        private void SetUpMovingArmiesTable() {
            movingArmiesTable.RowCount = MovingArmiesCount;

            MovingArmies.Each((army, i) => {
                var newRow = movingArmiesTable.ComponentAt<MovingArmyTableRow>(i);
                if (army.FactionId == Model.PlayerId) {
                    newRow.Faction = null;
                } else {
                    newRow.Faction = Model.FactionName(army.FactionId);
                    if (Model.PlayerId is FactionId myFid) {
                        if (Model.ActiveFactions[myFid].FactionRelationships.First(
                                    fr => fr.TargetFactionId == army.FactionId)
                                    is FactionRelationshipView frv &&
                            frv.RelationshipLevel ==
                                    FactionRelationshipView.Types.RelationshipLevel.Ally) {
                            newRow.FactionColor = Color.blue;
                        } else {
                            newRow.FactionColor = Color.red;
                        }
                    }
                }
                newRow.HeroCount = army.HeroCount;
                newRow.TroopCount = army.TroopCount;
                newRow.Origin = Model.Provinces[army.OriginProvinceId].Name;
                newRow.Destination = Model.Provinces[army.DestinationProvinceId].Name;
                if (CurrentProvince != null && army.DestinationProvinceId == CurrentProvince.Id) {
                    newRow.DestinationColor = Color.blue;
                } else {
                    newRow.DestinationColor = Color.black;
                }

                newRow.Gold = army.Gold;
                newRow.Food = army.Food;
                newRow.Selected = false;
                newRow.Selectable = false;
                newRow.RightSelectable = false;
            });
        }

        public void ProvinceHovered(ProvinceId? pid) {
            // Highlight moving armies table
            MovingArmies.Each((army, i) => {
                var row = movingArmiesTable.ComponentAt<MovingArmyTableRow>(i);
                if (army.DestinationProvinceId == pid || army.OriginProvinceId == pid) {
                    row.ShadeOn();
                } else {
                    row.ShadeOff();
                }
            });
        }

        void Start() { panel.SetActive(Model != null); }

        private bool IsHostileFaction(FactionId fid) {
            if (Model.PlayerId is FactionId myFid) {
                if (myFid == fid) return false;

                var fr = Model.MaybeDestroyedFaction(myFid).FactionRelationships.FirstOrDefault(
                        fr => fr.TargetFactionId == fid);

                if (fr == null) return false;

                return fr.RelationshipLevel ==
                       FactionRelationshipView.Types.RelationshipLevel.Hostile;
            }

            return false;
        }

        private int MovingArmiesCount => MovingArmies.Count();
        private IEnumerable<IncomingArmyView> MovingArmies =>
                Model.Provinces.Values.SelectMany(p => p.KnownIncomingArmies)
                        .OrderByDescending(a => IsHostileFaction(a.FactionId))
                        .ThenByDescending(a => a.FactionId == Model.PlayerId)
                        .ThenBy(a => CurrentProvince != null &&
                                     a.DestinationProvinceId != CurrentProvince.Id)
                        .ThenByDescending(a => a.HeroCount);
    }
}