#pragma once

#include <extra2d/platform/iinput.h>
#include <GLFW/glfw3.h>
#include <array>

namespace extra2d {

/**
 * @brief GLFW 输入实现
 */
class GLFWInput : public IInput {
public:
    GLFWInput();
    ~GLFWInput() override;

    void init() override;
    void shutdown() override;
    void update() override;

    // Keyboard
    bool down(Key key) const override;
    bool pressed(Key key) const override;
    bool released(Key key) const override;

    // Mouse
    bool down(Mouse btn) const override;
    bool pressed(Mouse btn) const override;
    bool released(Mouse btn) const override;
    Vec2 mouse() const override;
    Vec2 mouseDelta() const override;
    float scroll() const override;
    float scrollDelta() const override;
    void setMouse(const Vec2& pos) override;

    // Gamepad
    bool gamepad() const override;
    bool down(Gamepad btn) const override;
    bool pressed(Gamepad btn) const override;
    bool released(Gamepad btn) const override;
    Vec2 leftStick() const override;
    Vec2 rightStick() const override;
    float leftTrigger() const override;
    float rightTrigger() const override;
    void vibrate(float left, float right) override;

    // Touch
    bool touching() const override;
    int touchCount() const override;
    Vec2 touch(int index) const override;
    TouchPoint touchPoint(int index) const override;

    // GLFW specific
    void handleKeyEvent(int key, int scancode, int action, int mods);
    void handleMouseButtonEvent(int button, int action, int mods);
    void handleCursorPosEvent(double xpos, double ypos);
    void handleScrollEvent(double xoffset, double yoffset);
    void handleJoystickEvent(int jid, int event);

    void setWindow(GLFWwindow* window) { window_ = window; }

private:
    void updateGamepad();
    void openGamepad();
    void closeGamepad();
    
    float applyDeadzone(float value) const;
    
    // Keyboard state
    std::array<bool, static_cast<size_t>(Key::Count)> keyCurrent_;
    std::array<bool, static_cast<size_t>(Key::Count)> keyPrevious_;
    
    // Mouse state
    std::array<bool, static_cast<size_t>(Mouse::Count)> mouseCurrent_;
    std::array<bool, static_cast<size_t>(Mouse::Count)> mousePrevious_;
    Vec2 mousePos_;
    Vec2 mouseDelta_;
    float scroll_ = 0.0f;
    float scrollDelta_ = 0.0f;
    
    // Gamepad state
    std::array<bool, static_cast<size_t>(Gamepad::Count)> gamepadCurrent_;
    std::array<bool, static_cast<size_t>(Gamepad::Count)> gamepadPrevious_;
    Vec2 leftStick_;
    Vec2 rightStick_;
    float leftTrigger_ = 0.0f;
    float rightTrigger_ = 0.0f;
    int gamepadId_ = -1;
    
    float deadzone_ = 0.15f;
    
    GLFWwindow* window_ = nullptr;
};

} // namespace extra2d
