#ifndef INPUT_MANAGER_HPP_
#define INPUT_MANAGER_HPP_

#include <Item/Item.hpp>
#include <functional>
#include <string>
#include <vector>
#include <memory>
#include <Utilities/Extern.hpp>
#include <Entity/PhysicsEntity/CameraEntity/Player/Player.hpp>

class InputMethod;
class WorldDisplay;

/**
 * @brief Manages input methods and abstracts them away into actions.
 */
class InputManager final
{
public:
    typedef std::function<void()> ActionCallback;

private:
    struct ActionHandler
    {
        ActionCallback onStarts;
        ActionCallback onEnds;
    };

    WorldDisplay &worldDisplay;
    std::vector<std::unique_ptr<InputMethod>> inputMethods;
    std::unordered_map<std::string, ActionHandler> actionHandlers;

    void registerControlFlagAction(Player::ControlFlag flag, const std::string &action);

public:
    InputManager(WorldDisplay &worldDisplay);

    /**
     * @brief Called when an SDL event is received.
     */
    void onEvent(SDL_Event &event);

    /**
     * @brief Called by input methods from onEvent() when an action starts (e.g. key pressed).
     */
    void onActionStarts(const std::string &action);

    /**
     * @brief Called by input methods from onEvent() when an action ends (e.g. key released).
     */
    void onActionEnds(const std::string &action);

    /**
     * @brief Register callbacks for an action.
     */
    void registerActionHandler(const std::string &action, ActionCallback onStarts, ActionCallback onEnds);
};

#endif