#ifndef CONTROLLER_CHANNEL_HPP_
#define CONTROLLER_CHANNEL_HPP_

#include <Messenger/Messenger.hpp>
#include <Serialize/Nested.hpp>
#include <memory>
#include <Serialize/Serialize.hpp>

class Player;
class Controller;

/**
 * @brief An individual channel to which a controller can be bound.
 */
class ControllerChannel final
{
private:
    uint8_t channelId;

    std::unique_ptr<Controller> currentController;
    uint16_t currentStamp = 0;
    
    std::shared_ptr<Messenger> getPeer();

public:
    Player &player;

    ControllerChannel(Player &player, uint8_t channelId);

    Controller& attach(const std::string &id, uint16_t stamp);
    void detach();
    void update();
    void remoteCall(uint8_t opcode, uint64_t promiseId, const NestedPayload &payload);
    void remoteReturn(uint64_t promiseId, const NestedPayload &payload);
    void dispatch(uint8_t opcode, uint16_t stamp, uint64_t promiseId, const NestedPayload &payload);
    void resolve(uint16_t stamp, uint64_t promiseId, const NestedPayload &payload);
    bool hasPeer();
    void onClosedByClient(uint16_t stamp);
    uint16_t getStamp();

    friend class Player;
    friend class WorldDisplay;
};

#endif