using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Sirenix.Utilities;
using UnityEngine;
using UnityEngine.UIElements;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Weapon;
using VOID.UserInterface.Game.Util;

namespace VOID.UserInterface.Game.Tooltip
{
    public class WeaponTooltipUI : ITooltip
    {
        // VisualElement - Container
        private readonly VisualElement _templateElement;
        
        // VisualElements - Sections
        private readonly VisualElement _titleSection;
        private readonly VisualElement _mainDetailsSection;
        private readonly VisualElement _detailsSection;
        private readonly VisualElement _descriptionSection;
        private readonly VisualElement _footSection;
        
        // VisualElements - Data
        private readonly SlotUI _weaponIcon = new();
        private readonly List<DetailsElement> _mainDetails = new();
        private readonly List<DetailsElement> _details = new();
        private readonly Label _weaponName;
        private readonly Label _weaponQuality;
        private readonly Label _weaponType;
        private readonly Label _weaponDescription;
        private readonly Label _weaponValue;
        private readonly Label _weaponWeight;

        public WeaponTooltipUI(VisualElement templateElement)
        {
            // Tooltip for this type
            _templateElement = templateElement.Q(null, "tooltip");
            
            // Sections
            _titleSection = templateElement.Q("title-section");
            _mainDetailsSection = templateElement.Q("main-details-section");
            _detailsSection = templateElement.Q("details-section");
            _descriptionSection = templateElement.Q("description-section");
            _footSection = templateElement.Q("foot-section");
            
            // Elements
            _weaponIcon.Init(templateElement.Q("weapon-icon"), SlotType.None, -1);
            _weaponName = templateElement.Q<Label>("weapon-name");
            _weaponQuality = templateElement.Q<Label>("weapon-quality");
            _weaponType = templateElement.Q<Label>("weapon-type");
            _weaponDescription = templateElement.Q<Label>("weapon-description");
            _weaponValue = templateElement.Q<Label>("weapon-value");
            _weaponWeight = templateElement.Q<Label>("weapon-weight");
        }

        public void Show(WeaponObject weapon)
        {
            _weaponIcon.Set(weapon);
            _templateElement.style.display = DisplayStyle.Flex;
            
            FillBasicInfo(weapon);
            FillMainDetails(weapon);
            FillDetails(weapon);
        }

        public void Hide()
        {
            _templateElement.style.display = DisplayStyle.None;
        }

        public Vector2 GetSize()
        {
            return new Vector2(_templateElement.worldBound.width, _templateElement.worldBound.height);
        }

        private void FillBasicInfo(WeaponObject weapon)
        {
            _weaponName.text = weapon.basicData.finalName;
            _weaponQuality.text = weapon.itemData.quality.displayName;
            _weaponType.text = weapon.weaponData.weaponType + " (" + weapon.weaponData.weaponCarryType + ")";
            _weaponDescription.text = weapon.basicData.description;
            _descriptionSection.style.display = _weaponDescription.text.IsNullOrWhitespace() ? DisplayStyle.None : DisplayStyle.Flex;
            _weaponValue.text = weapon.itemData.finalValue.ToString(CultureInfo.InvariantCulture);
            _weaponWeight.text = weapon.itemData.finalWeight.ToString(CultureInfo.InvariantCulture);
        }

        private void FillMainDetails(WeaponObject weapon)
        {
            _mainDetailsSection.Clear();

            // Weapon's damage
            var weaponDamage = $"Damage: {weapon.weaponData.damageMin} - {weapon.weaponData.damageMax} ({weapon.weaponData.damageType})";
            _mainDetails.Add(new DetailsElement(_mainDetailsSection, null, new[] { weaponDamage }));

            // Weapons's Critical Damage Chance
            var criticalChance = $"Crit chance: {weapon.weaponData.criticalDamageChange * 100}%";
            _mainDetails.Add(new DetailsElement(_mainDetailsSection, null, new[] { criticalChance }));

            // Weapons's Critical Damage Multiplier
            var criticalMultiplier = $"Crit multiplier: {weapon.weaponData.criticalDamageMultiplier * 100}%";
            _mainDetails.Add(new DetailsElement(_mainDetailsSection, null, new[] { criticalMultiplier }));
        }

        private void FillDetails(WeaponObject weapon)
        {
            _detailsSection.Clear();
            
            // All effects except damage
            var simpleDescriptions = weapon.wearableData.effects
                .Select(effect => effect.GetSimpleDescription())
                .ToArray();
            _details.Add(new DetailsElement(_detailsSection, null, simpleDescriptions));
        }
    }
}