#pragma once

#include <robin_hood.h>
#include <vector>

#include <GLFW/glfw3.h>

enum class Input {
    Forward, Backward, Left, Right, Up, Down,
    Mouse, Debug, Throw, Quit
};
enum class Mouse {
    Left = GLFW_MOUSE_BUTTON_LEFT,
    Right = GLFW_MOUSE_BUTTON_RIGHT
};

/// Handle inputs with name to key mapping table
class InputMap {
public:
    InputMap(GLFWwindow*);
    ~InputMap();

    void saveKeys();

    bool isDown(Input input) const;
    bool wasDown(Input input) const;
    bool isPressing(Input input) const;
    bool isReleasing(Input input) const;

    void toggle(bool &val, Input input) const;

    bool isDown(Mouse input) const;
    bool wasDown(Mouse input) const;
    bool isPressing(Mouse input) const;
    bool isReleasing(Mouse input) const;

    void poll() const;

private:
    GLFWwindow *window;
    robin_hood::unordered_map<Input, int> Map = {
        {Input::Forward, GLFW_KEY_W},
        {Input::Backward, GLFW_KEY_S},
        {Input::Left, GLFW_KEY_A},
        {Input::Right, GLFW_KEY_D},
        {Input::Up, GLFW_KEY_SPACE},
        {Input::Down, GLFW_KEY_LEFT_SHIFT},
        {Input::Mouse, GLFW_KEY_E},
        {Input::Debug, GLFW_KEY_F3},
        {Input::Throw, GLFW_KEY_B},
        {Input::Quit, GLFW_KEY_ESCAPE}
    };
    const std::vector<Input> Toggles = {
        Input::Mouse, Input::Debug, Input::Throw
    };
    robin_hood::unordered_map<Input, bool> Previous;

    bool PreviousLeft;
    bool PreviousRight;
};
