#ifndef INVENTORY_HPP_INCLUDED
#define INVENTORY_HPP_INCLUDED

#include "../../../Core/Types/Box.hpp"
#include "../../../Core/Types/Convex.hpp"
#include "../../../Game/Interactable/Item.hpp"
#include <functional>
#include <vector>
#include <cstdint>
#include <string>

namespace Inventory
{
    bool IsOpen();
    bool Open(bool UseHotkey = true);
    std::int32_t GetTabHotkey();

    std::vector<std::int32_t> GetItemIDs();
    std::vector<std::string> GetItemNames();
    std::vector<std::int32_t> GetItemAmounts();

    std::vector<Interactable::Item> GetItems();
    std::vector<Interactable::Item> GetItems(std::int32_t ID);
    std::vector<Interactable::Item> GetItems(const std::string& Name);
    std::vector<Interactable::Item> GetItems(const std::vector<std::int32_t>& IDs);
    std::vector<Interactable::Item> GetItems(const std::vector<std::string>& Names);
    std::vector<Interactable::Item> GetItems(const std::function<bool (const Interactable::Item&)>& Filter);

    Interactable::Item GetItem(std::int32_t ID);
    Interactable::Item GetItem(const std::string& Name);
    Interactable::Item GetItem(const std::vector<std::int32_t>& IDs);
    Interactable::Item GetItem(const std::vector<std::string>& Names);
    Interactable::Item GetItem(const std::function<bool (const Interactable::Item&)>& Filter);

    bool IsEmpty();
    bool IsFull();

    bool IsItemSelected();
    bool IsItemSelected(std::int32_t ID);
    bool IsItemSelected(const std::string& Name);
    bool IsItemSelected(const Interactable::Item& Item);

    std::string GetItemSelectedName();

    std::int32_t Count(std::int32_t ID);
    std::int32_t Count(const std::string& Name);
    std::int32_t Count(const Interactable::Item& Item);
    std::int32_t Count(const std::vector<std::int32_t>& IDs);
    std::int32_t Count(const std::vector<std::string>& Names);
    std::int32_t Count(const std::vector<Interactable::Item>& Items);

    std::int32_t CountOccupied();
    std::int32_t CountEmpty();

    std::int32_t GetIndexOf(std::int32_t ID);
    std::int32_t GetIndexOf(const std::string& Name);
    std::int32_t GetIndexOf(const std::vector<std::int32_t>& IDs); // Returns first found ID index
    std::int32_t GetIndexOf(const std::vector<std::string>& Names); // Returns first found Name Index

    std::vector<std::int32_t> GetIndicesOf(std::int32_t ID);
    std::vector<std::int32_t> GetIndicesOf(const std::string& Name);
    std::vector<std::int32_t> GetIndicesOf(const std::vector<std::int32_t>& IDs);
    std::vector<std::int32_t> GetIndicesOf(const std::vector<std::string>& Names);

    std::vector<Box> GetSlotBoxes();
    std::vector<Box> GetBoxesOf(std::int32_t ID);
    std::vector<Box> GetBoxesOf(const std::string& Name);

    bool Contains(std::int32_t ID);
    bool Contains(const std::string& Name);
    bool Contains(const Interactable::Item& Item);
    bool Contains(const std::vector<std::int32_t>& IDs); // true if all items are found at least once
    bool Contains(const std::vector<std::string>& Names); // true if all items are found at least once
    bool Contains(const std::vector<Interactable::Item>& Items);

    bool ContainsAny(const std::vector<std::int32_t>& IDs);
    bool ContainsAny(const std::vector<std::string>& Names);
    bool ContainsAny(const std::vector<Interactable::Item>& Items);

    bool ContainsOnly(std::int32_t ID);
    bool ContainsOnly(const std::string& Name);
    bool ContainsOnly(const Interactable::Item& Item);
    bool ContainsOnly(const std::vector<std::int32_t>& IDs);
    bool ContainsOnly(const std::vector<std::string>& Names);
    bool ContainsOnly(const std::vector<Interactable::Item>& Items);

    bool Use(std::int32_t ID, std::int32_t ID2 = -1, bool UseSecondFirst = false);
    bool Use(const std::string& Name, const std::string& Name2 = "", bool UseSecondFirst = false);
    bool Use(const Interactable::Item& Item, const Interactable::Item& Item2 = Interactable::Item(), bool UseSecondFirst = false);

    bool Equip(std::int32_t ID);
    bool Equip(const std::string& Name);
    bool Equip(const Interactable::Item& Item);

    bool Drop(std::int32_t ID, bool AllowShiftClick = true);
    bool Drop(const std::string& Name, bool AllowShiftClick = true);
    bool Drop(const Interactable::Item& Item, bool AllowShiftClick = true);
}

#endif // INVENTORY_HPP_INCLUDED
