using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class Inventory : MonoBehaviour
{
    public ItemSlot[] itemSlots;
    public BackPackType ownedBackpackType;

    InventorySlotUI inventoryDisplay;
    private bool showingInventory = false;

    private void Update()
    {
        if (inventoryDisplay == null)
        {
            inventoryDisplay = GameObject.FindWithTag("InventorySlots").GetComponent<InventorySlotUI>();
            inventoryDisplay.gameObject.SetActive(false);
        }

        if (Input.GetKeyDown(KeyCode.Tab))
        {
            if (showingInventory)
            {
                inventoryDisplay.HideSlots();
                Time.timeScale = 1;
            }
            else
            {
                inventoryDisplay.ShowSlots();
                Time.timeScale = 0;
            }

            showingInventory = !showingInventory;
        }
    }

    // we'll set this up to only try to add one item to the inventory at a time for now
    // there won't be stacked items in the wild for right now
    public bool AddItem(Item item, int quantity)
    {
        // first try to stack
        for (int i = 0; i < itemSlots.Length; i++)
        {
            if (itemSlots[i].item == item.id && itemSlots[i].quantity < item.maxStack)
            {
                itemSlots[i].quantity += 1;
                return true;
            }
        }

        // no stack to add to, try to find an empty slot
        for (int i = 0; i < itemSlots.Length; i++)
        {
            if (itemSlots[i].item == ItemIdEnum.NONE)
            {
                itemSlots[i] = new ItemSlot();

                itemSlots[i].quantity = 1;
                itemSlots[i].item = item.id;
                return true;
            }
        }

        // no open slots, no open stacks, we can't add the item
        return false;
    }

    public bool RemoveItemQuantity(ItemIdEnum itemId, int quantity)
    {
        if (GetItemQuantity(itemId) >= quantity)
        {
            int currentQuantity = quantity;

            for (int i = 0; i < itemSlots.Length; i++)
            {
                if (itemSlots[i].item == itemId)
                {
                    // we are trying to remove less items than what exists in the current
                    // stack, so just subtract from the stack 
                    if (currentQuantity < itemSlots[i].quantity)
                    {
                        itemSlots[i].quantity -= currentQuantity;
                        break;
                    }
                    else if (currentQuantity == itemSlots[i].quantity)
                    {
                        // we have exactly enough in the current slot, so nullify it and
                        // exit
                        itemSlots[i].item = ItemIdEnum.NONE;
                        break;
                    }
                    else
                    {
                        // we don't have enough in the stack, but we DO have enough in our
                        // inventory. nullify the stack, subtract that number from the current
                        // count, and move to the next item
                        currentQuantity -= itemSlots[i].quantity;
                        itemSlots[i].item = ItemIdEnum.NONE;
                    }
                }
            }
            
            return true;
        }
        else
        {
            return false;
        }
    }

    public int GetItemQuantity(ItemIdEnum itemId)
    {
        int itemCount = 0;

        foreach (ItemSlot slot in itemSlots)
        {
            if (slot.item == itemId)
            {
                itemCount += slot.quantity;
            }
        }

        return itemCount;
    }

    private int GetItemSlotNum()
    {
        switch (ownedBackpackType)
        {
            case BackPackType.Pockets:
                return 8;
            case BackPackType.SmallBag:
                return 16;
            case BackPackType.LargeBag:
                return 32;
        }

        return 0;
    }

    #region Inventory Save/Load
    public void SaveInventory(ref InventorySaveData data)
    {
        data.itemSlots = itemSlots;
        data.ownedBackpack = ownedBackpackType;
    }

    public void LoadInventory(InventorySaveData data)
    {
        ownedBackpackType = data.ownedBackpack;

        if (data.itemSlots != null && data.itemSlots.Length > 0)
        {
            itemSlots = data.itemSlots;

            // list is somehow corrupted, fill in the rest of the slots
            if (itemSlots.Length < GetItemSlotNum())
            {
                ItemSlot[] newSlots = new ItemSlot[GetItemSlotNum()];

                for (int i = 0; i < itemSlots.Length; i++)
                {
                    if (itemSlots[i] != null)
                        newSlots[i] = itemSlots[i];
                    else
                        newSlots[i] = new ItemSlot();
                }

                itemSlots = newSlots;
            }
        }
        else if (data.itemSlots != null && data.itemSlots.Length > GetItemSlotNum())
        {
            // list is bigger than it should be, generate new slots of the proper size
            // and save just the items in the slots we SHOULD have. (shouldn't ever happen)
            ItemSlot[] newSlots = new ItemSlot[GetItemSlotNum()];

            for (int i = 0; i < newSlots.Length; i++)
            {
                if (itemSlots[i] != null)
                    newSlots[i] = itemSlots[i];
                else
                    newSlots[i] = new ItemSlot();
            }

            itemSlots = newSlots;
        }
        else
        {
            itemSlots = new ItemSlot[GetItemSlotNum()];
            for (int i = 0; i < itemSlots.Length; i++)
            {
                itemSlots[i] = new ItemSlot();
            }
        }
    }
    #endregion
}

public enum BackPackType
{
    Pockets = 0,
    SmallBag = 1,
    LargeBag = 2
}

[System.Serializable]
public class ItemSlot
{
    public int quantity;
    public ItemIdEnum item;
}

[System.Serializable]
public struct InventorySaveData
{
    public ItemSlot[] itemSlots;
    public BackPackType ownedBackpack;
}
