using UnityEngine;
using UnityEngine.UIElements;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Item;
using VOID.ScriptableObjects.Abilities;

namespace VOID.UserInterface.Game.Util
{
    /// <summary>
    /// Manages all visuals inside slot: <see cref="ItemObject"/> or <see cref="BasicAbility"/>,
    /// including: image, border and background
    /// </summary>
    public class SlotUI
    {
        // Where slot belongs with its index
        public SlotType slotType { get; private set; }
        public int slotIndex { get; private set; }

        // Content of slot
        public bool isEmpty { get; private set; } = true;
        public ItemObject item { get; private set; }
        public BasicAbility ability { get; private set; }
        
        // Elements
        private VisualElement _templateElement;
        private VisualElement _backgroundElement;
        private VisualElement _borderElement;
        private VisualElement _iconElement;

        /// <summary>
        /// Initializes <see cref="SlotUI"/> on existing slot visual element.
        /// </summary>
        /// <param name="templateElement">Existing template to use for this slot</param>
        /// <param name="slotType">Defines to which UI it belongs.</param>
        /// <param name="slotIndex">Defines specific slot index in UI.</param>
        public void Init(VisualElement templateElement, SlotType slotType, int slotIndex)
        {
            _templateElement = templateElement;
            this.slotType = slotType;
            this.slotIndex = slotIndex;

            // Find all Slot's elements
            _backgroundElement = _templateElement.Q("background");
            _borderElement = _templateElement.Q("border");
            _iconElement = _templateElement.Q("icon");

            // Binding component to element
            _templateElement.dataSource = this;
            _templateElement.pickingMode = PickingMode.Position;
        }

        /// <summary>
        /// Initializes completly new <see cref="SlotUI"/> inside given parent.
        /// </summary>
        /// <param name="parentElement">Create new slot as child in given parent.</param>
        /// <param name="slotType">Defines to which UI it belongs.</param>
        /// <param name="slotIndex">Defines specific slot index in UI.</param>
        /// <param name="name">Name for new Visual Element</param>
        public void InitNew(VisualElement parentElement, SlotType slotType, int slotIndex, string name = null)
        {
            // Create Slot (from template) in GUI
            var templateElement = GameUI.current.slotTemplate.CloneTree().contentContainer;
            templateElement.name = name ?? "slot";
            templateElement.AddToClassList("slot");
            templateElement.AddToClassList("slot-medium");
            parentElement.Add(templateElement);
            
            Init(templateElement, slotType, slotIndex);
        }

        /// <summary>
        /// Change slot index. Useful when slot don't move anywhere, but whole counting change.
        /// </summary>
        public void ChangeIndex(int newIndex)
        {
            slotIndex = newIndex;
        }
        
        /// <summary>
        /// Put <see cref="ItemObject"/> into this slot and update all visuals.
        /// </summary>
        public void Set(ItemObject item)
        {
            Clear();
            if (!item) return;
            this.item = item;
            UpdateIconElement(item.basicData.image, item.itemData.quality.background, item.itemData.quality.border);
        }

        /// <summary>
        /// Put <see cref="BasicAbility"/> into this slot and update all visuals.
        /// </summary>
        public void Set(BasicAbility ability)
        {
            Clear();
            if (!ability) return;
            this.ability = ability;
            UpdateIconElement(ability.displayIcon, ability.quality.background, ability.quality.border);
        }

        private void UpdateIconElement(Texture2D icon, Texture2D background, Texture2D border)
        {
            isEmpty = false;
            _backgroundElement.style.backgroundImage = new StyleBackground(background);
            _iconElement.style.backgroundImage = new StyleBackground(icon);
            _borderElement.style.backgroundImage = new StyleBackground(border);
        }

        /// <summary>
        /// Remove <see cref="ItemObject"/> or <see cref="BasicAbility"/> from this slot and make it empty.
        /// </summary>
        public void Clear()
        {
            _iconElement.style.backgroundImage = new StyleBackground(StyleKeyword.Null);
            ability = null;
            item = null;
            isEmpty = true;
        }

        /// <summary>
        /// Destroy whole <see cref="SlotUI"/> with its <see cref="VisualElement"/>.
        /// </summary>
        public void Destroy()
        {
            _templateElement.parent.Remove(_templateElement);
        }
    }
}