#ifndef INPUT_HPP
#define INPUT_HPP

#include "../core.hpp"
#include <map>

#define MAX_AXIS 10

namespace OpenEngine {
    class OE_API Input
    {
        public:
            Input(const Input&) = delete;
            Input& operator=(const Input&) = delete;

            inline static bool IsKeyPressed(int keycode) { return instance->IsKeyPressedImpl(keycode); };

            inline static bool IsMouseButtonPressed(int button) { return instance->IsMouseButtonPressedImpl(button); };

            inline static std::pair<float, float> GetMousePosition() { return instance->GetMousePositionImpl(); };
            inline static bool GetMouseX() { return instance->GetMouseXImpl(); };
            inline static bool GetMouseY() { return instance->GetMouseYImpl(); };

            inline static bool JoystickExists(unsigned int joystick) { return instance->JoystickExistsImpl(joystick); };
            inline static std::map<unsigned int, std::string> GetJoystickList() { return instance->GetJoystickListImpl(); };

            inline static float GetJoystickAxis(unsigned int joystick, unsigned int axis) { return instance->GetJoystickAxisImpl(joystick, axis); };
            inline static const float* GetJoystickAxes(unsigned int joystick) { return instance->GetJoystickAxesImpl(joystick); };
            inline static unsigned int GetJoystickAxesCount(unsigned int joystick) { return instance->GetJoystickAxesCountImpl(joystick); };

            inline static bool IsJoystickButtonPressed(unsigned int joystick, unsigned int button) { return instance->IsJoystickButtonPressedImpl(joystick, button); };

        protected:
            Input() = default;
 
            virtual bool IsKeyPressedImpl(int keycode) = 0;

            virtual bool IsMouseButtonPressedImpl(int button) = 0;

            virtual std::pair<float, float> GetMousePositionImpl() = 0;
            virtual float GetMouseXImpl() = 0;
            virtual float GetMouseYImpl() = 0;

            virtual bool JoystickExistsImpl(unsigned int joystick) = 0;
            virtual std::map<unsigned int, std::string> GetJoystickListImpl() = 0;
            virtual const std::string GetJoystickNameImpl(unsigned int joystick) = 0;

            virtual float GetJoystickAxisImpl(unsigned int joystick, unsigned int axis) = 0;
            virtual const float* GetJoystickAxesImpl(unsigned int joystick) = 0;
            virtual unsigned int GetJoystickAxesCountImpl(unsigned int joystick) = 0;

            virtual bool IsJoystickButtonPressedImpl(unsigned int joystick, unsigned int button) = 0;

        private:
            inline static const std::string GetJoystickName(unsigned int joystick) { return instance->GetJoystickNameImpl(joystick); };

            static Input* instance;
    };
}

#endif // INPUT_HPP
