using EFT.InventoryLogic;
using SPT.Reflection.Utils;
using System.Text;
using KeycardTemplate = GClass2623;
using ArmorTemplate = GClass2550;
using ArmoredRigTemplate = GClass2602;
using MagazineTemplate = GClass2586;

namespace LootValueEX.Extensions
{
    internal static class ItemExtensions
    {
        internal static bool IsExamined(this Item? item) => item != null && ClientAppUtils.GetMainApp().GetClientBackEndSession().Profile.Examined(item);
        internal static float GetItemAttribute(this Item? item, EItemAttributeId attributeId)
        {
            if (item == null)
                return -1f;
            try
            {
                return item.Attributes.Single(att => att.Id.Equals(attributeId)).Base();
            }
            catch (InvalidOperationException)
            {
                return -1f;
            }
        }
        internal static string GetCustomHash(this Item? item)
        {
            if (item == null)
                return string.Empty;
            StringBuilder prehashString = new StringBuilder();
            item.GetAllItems().Where(prop => !prop.Equals(item)).ExecuteForEach(prop => prehashString.Append(prop.GetCustomHash()));
            if (item.Template.Equals(typeof(MagazineTemplate))){
                MagazineTemplate magTemplate = (MagazineTemplate)item.Template;
                magTemplate.Cartridges.ExecuteForEach(prop => prop.Items.ExecuteForEach(ammo => prehashString.Append(ammo.GetCustomHash())));
            }
            string itemHashTemplate = string.Format("{0}|{1}|{2}|{3}", prehashString.ToString(), item.TemplateId, item.GetDurability(), item.GetUses());
            return Utils.HashingUtils.ConvertToSha256(itemHashTemplate);
        }
#if DEBUG
        internal static string AttributesToString(this Item? item)
        {
            if (item == null)
                return String.Empty;

            if (item.Attributes.IsNullOrEmpty()) 
                return String.Empty;

            StringBuilder sb = new StringBuilder();
            item.Attributes.ForEach(attr => sb.Append($"\n{attr.Id}\n\tName: {attr.Name}\n\tBase Value: {attr.Base()}\n\tString value: {attr.StringValue()}\n\tDisplay Type: {attr.DisplayType()}"));
            return sb.ToString();
        }
#endif
        internal static float GetDurability(this Item? item)
        {
            if (item == null)
                return -1f;
            switch (item.Template)
            {
                case ArmoredRigTemplate armoredRig:
                case ArmorTemplate armor:
                    return Utils.ItemUtils.GetArmorDurability(item.GetItemComponentsInChildren<RepairableComponent>(true));
                default:
                    return item.GetItemAttribute(EItemAttributeId.Durability);
            }
        }
        internal static float GetUses(this Item? item)
        {
            if (item == null)
                return -1f;
            switch (item.Template)
            {
                case KeycardTemplate:
                    KeyComponent keyComponent = item.GetItemComponent<KeyComponent>();
                    return keyComponent.Template.MaximumNumberOfUsage - keyComponent.NumberOfUsages;
                case Meds2Class:
                    if (item.TryGetItemComponent(out MedKitComponent medKitComponent))
                        return medKitComponent.HpResource;
                    return -1f;
                case MagazineTemplate:
                    MagazineClass? magazineClass = item as MagazineClass;
                    return magazineClass != null ? magazineClass.Count : -1f;
                case AmmoBoxTemplate:
                    AmmoBox? ammoBox = item as AmmoBox;
                    return ammoBox != null ? ammoBox.Count : -1f;
                default:
                    return -1f;
            }
        }
    }
}
