#ifndef EXCHANGE_HPP_INCLUDED
#define EXCHANGE_HPP_INCLUDED

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

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

        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;

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

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

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

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

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

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


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


        typedef enum COLLECT_SLOT
        {
            ONE,
            TWO
        } COLLECT_SLOT;

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

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

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

};

/** @} */

#endif // EXCHANGE_HPP_INCLUDED
