#ifndef EXCHANGE_HPP_INCLUDED
#define EXCHANGE_HPP_INCLUDED

#include "../../Core/Classes/ExchangeOffer.hpp"
#include <cstdint>
#include <string>
#include <vector>
#include <functional>

namespace Exchange
{
    typedef std::int32_t SLOT;

    typedef enum SLOT_STATE
    {
        STATE_EMPTY = 0,
        STARTING_BUY_OFFER = 1,
        BUY_OFFER_INCOMPLETE = 2,
        BUY_OFFER_UPDATING = 3,
        BUY_OFFER_CANCELING = 4,
        BUY_OFFER_COMPLETE = 5,
        STARTING_SELL_OFFER = 9,
        SELL_OFFER_INCOMPLETE = 10,
        SELL_OFFER_UPDATING = 11,
        SELL_OFFER_CANCELING = 12,
        SELL_OFFER_COMPLETE = 13,
        STATE_DISABLED = 14,
        STATE_UNDEFINED = 15
    } SLOT_STATE;

    typedef enum SLOT_MODE
    {
        BUY = 0,
        SELL = 1,
        MODE_DISABLED = 2,
        MODE_UNDEFINED = 3
    } SLOT_MODE;

    typedef enum COLLECT_METHOD
    {
        ITEM,
        NOTE,
        BANK
    } COLLECT_METHOD;

    bool IsOpen();
    bool Open();
    bool Close();
    SLOT_STATE GetSlotState(const Exchange::SLOT Slot);
    bool SlotOccupied(const Exchange::SLOT Slot);
    std::vector<SLOT_STATE> GetAllSlotStates();
    bool AllSlotsOccupied();
    std::int32_t GetOfferIndex();

    SLOT_MODE GetOfferMode();
    std::int32_t GetOfferItemID();
    std::string GetOfferItemName();
    std::int32_t GetOfferAmount();
    std::int32_t GetOfferPrice();
    bool IsOfferOpen();
    bool CloseOffer();
    bool IsOffersOpen();
    bool SlotUsable(const Exchange::SLOT Slot);
    bool CanCollect();

    bool CollectAll(const bool Inventory = true);
    bool Collect(const Exchange::COLLECT_METHOD Method = Exchange::BANK);

    bool IsBuyOfferOpen();
    bool IsSellOfferOpen();
    bool OpenBuyOffer(const Exchange::SLOT Slot = -1);
    bool OpenSellOffer(const Exchange::SLOT Slot = -1);

    Exchange::SLOT GetBuyOffer(std::int32_t ID);
    Exchange::SLOT GetBuyOffer(const std::string& Name);
    Exchange::SLOT GetBuyOffer(const std::function<bool (const Internal::ExchangeOffer&)>& Filter);
    std::vector<Exchange::SLOT> GetBuyOffers(std::int32_t ID);
    std::vector<Exchange::SLOT> GetBuyOffers(const std::string& Name);
    std::vector<Exchange::SLOT> GetBuyOffers(const std::function<bool (const Internal::ExchangeOffer&)>& Filter);

    Exchange::SLOT GetSellOffer(std::int32_t ID);
    Exchange::SLOT GetSellOffer(const std::string& Name);
    Exchange::SLOT GetSellOffer(const std::function<bool (const Internal::ExchangeOffer&)>& Filter);
    std::vector<Exchange::SLOT> GetSellOffers(std::int32_t ID);
    std::vector<Exchange::SLOT> GetSellOffers(const std::string& Name);
    std::vector<Exchange::SLOT> GetSellOffers(const std::function<bool (const Internal::ExchangeOffer&)>& Filter);


    bool SetSellItem(const std::string& Name);
    bool SetSellItem(std::int32_t ID);
    bool SetBuyItem(const std::string& Name);
    bool SetOfferAmount(std::uint32_t Amount);
    bool SetOfferPrice(std::uint32_t Price);
    bool SetOfferGuidePrice();
    bool ConfirmOffer();


    typedef enum COLLECT_SLOT
    {
        ONE,
        TWO
    } COLLECT_SLOT;

    std::string GetCollectSlotName(Exchange::COLLECT_SLOT Slot);
    std::int32_t GetCollectSlotID(Exchange::COLLECT_SLOT Slot);
    std::int32_t GetCollectSlotAmount(Exchange::COLLECT_SLOT Slot);

    bool AbortOffer(const Exchange::SLOT Slot = -1);

    bool OpenOffer(const Exchange::SLOT Slot);
}

#endif // EXCHANGE_HPP_INCLUDED
