#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>

namespace Bank
{
    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;

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

    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);

    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 GetIndexOf(std::int32_t ID);
    std::int32_t GetIndexOf(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);

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

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

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

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

    bool DepositAllExcept(std::int32_t ID, double DepsositAllChance = 0.00); // DepositAllChance = the chance it will click deposit all on the individual item, instead of left clicking if possible. Will deposit all if the current default quantity is not enough to one click it
    bool DepositAllExcept(const std::string& Name, double DepsositAllChance = 0.00);
    bool DepositAllExcept(const Interactable::Item& Item, double DepsositAllChance = 0.00);
    bool DepositAllExcept(const std::vector<std::int32_t>& IDs, double DepsositAllChance = 0.00);
    bool DepositAllExcept(const std::vector<std::string>& Names, double DepsositAllChance = 0.00);
    bool DepositAllExcept(const std::vector<Interactable::Item>& Items, double DepsositAllChance = 0.00);

    bool DepositAll();
    bool DepositEquipment();

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

    PIN_STEP GetEnterPinStep();
    bool IsEnterPinOpen();
    bool EnterPin(bool TerminateOnError = true);

    std::int32_t GetDefaultWithdrawQuantity();
    bool SetDefaultWithdrawQuantity(std::int32_t Amount);
}

#endif // BANK_HPP_INCLUDED
