#ifndef CONTROLLER_H
#define CONTROLLER_H

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include "utils/Array.h"
#include "input/Button.h"

class Controller final {
    static constexpr int BUTTON_AMOUNT = 13;
    Array<Button, BUTTON_AMOUNT> buttons;
    Array<int, 1 + GLFW_KEY_LAST> keyToButton;
    Array<int, 1 + GLFW_GAMEPAD_BUTTON_LAST> gamepadToButton;

    struct Axis {
        int positive;
        int negative;
        float split;
        Axis();
    };
    Array<Axis, 1 + GLFW_GAMEPAD_AXIS_LAST> axisToButton;

    int activeController;

public:
    static constexpr int UNKNOWN = -1;
    static constexpr int A = 0;
    static constexpr int B = 1;
    static constexpr int X = 2;
    static constexpr int Y = 3;
    static constexpr int L = 4;
    static constexpr int R = 5;
    static constexpr int START = 6;
    static constexpr int SELECT = 7;
    static constexpr int LEFT = 8;
    static constexpr int RIGHT = 9;
    static constexpr int UP = 10;
    static constexpr int DOWN = 11;

    Controller();
    bool mapKey(int key, int button);

    void press(int key);
    void release(int key);
    void tick();

    int getButtonAmount() const;
    const char* getName(int button) const;
    bool isDown(int button) const;
    int getDownTime(int button) const;
    bool wasReleased(int button) const;

private:
    int getRangeMask(int button) const;
    bool searchForGamepad();
    void checkGamepad();
    bool mapGamepad(int gamepad, int button);
    bool mapAxis(int axis, int positiveButton, int negativeButton, float split = 0.5f);
};

#endif