#ifndef BANK_HPP_INCLUDED
#define BANK_HPP_INCLUDED

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

/** @addtogroup Interfaces
* @{
*/
class Bank
{
    public:

        enum BANK_AMOUNT
        {
            ALL         = -1,
            ALL_BUT_ONE = 0
        };

        typedef enum WITHDRAW_MODE
        {
            ITEM,
            NOTED
        } WITHDRAW_MODE;

        typedef enum PIN_STEP
        {
            FIRST,
            SECOND,
            THIRD,
            FOURTH,
            SUBMITTING,
            TOO_MANY_ATTEMPTS,
            BANK_OPEN
        } PIN_STEP;

        static bool IsOpen();
        static bool Close(bool AllowEsc = true);

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

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

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

        static std::int32_t Count(std::int32_t ID);
        static std::int32_t Count(const std::string& Name);
        static std::int32_t Count(const Interactable::Item& Item);

        static std::int32_t GetIndexOf(std::int32_t ID);
        static std::int32_t GetIndexOf(const std::string& Name);

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

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

        static std::int32_t GetCurrentTab();
        static std::int32_t GetTabOf(std::int32_t ID);
        static std::int32_t GetTabOf(const std::string& Name);
        static std::int32_t GetTabOf(const Interactable::Item& Item);
        static bool OpenTab(std::int32_t Tab);

        static bool ScrollTo(std::int32_t ID, bool OpenRespectiveTab = false);
        static bool ScrollTo(const std::string& Name, bool OpenRespectiveTab = false);
        static bool ScrollTo(const Interactable::Item& Item, bool OpenRespectiveTab = false);

        // -1 = all, 0 = all-but-one
        static bool Withdraw(std::int32_t ID, std::int32_t Amount, bool OpenRespectiveTab = false);
        static bool Withdraw(const std::string& Name, std::int32_t Amount, bool OpenRespectiveTab = false);
        static bool Withdraw(const Interactable::Item& Item, std::int32_t Amount, bool OpenRespectiveTab = false);

        // -1 = all
        static bool Deposit(std::int32_t ID, std::int32_t Amount);
        static bool Deposit(const std::string& Name, std::int32_t Amount);
        static bool Deposit(const Interactable::Item& Item, std::int32_t Amount);

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

        static bool DepositAll();
        static bool DepositEquipment();

        static WITHDRAW_MODE GetWithdrawMode();
        static bool SetWithdrawMode(WITHDRAW_MODE Mode);

        static PIN_STEP GetEnterPinStep();
        static bool IsEnterPinOpen();
        static bool EnterPin(bool Terminate = true);
};

/** @} */

#endif // BANK_HPP_INCLUDED
