#if BACKEND == SDL3

#include "backends/backend.h"
#include "state.h"
#include "mini/view/view.h"

namespace backend
{
    namespace input
    {
        void reset() {
            key::just_pressed = 0;
            key::has_text_input = false;
            key::text_input_buffer[0] = '\0';
            mouse::just_pressed = 0;
            mouse::double_click = false;
            mouse::w = 0;
            pad::just_pressed = SDL_GAMEPAD_BUTTON_INVALID;
        }

        namespace key
        {
            const bool *keys;
            uint8_t just_pressed = 0;
            char text_input_buffer[10];
            bool has_text_input = false;

            bool down(uint8_t i) {
                return keys[i];
            }

            bool press(uint8_t i) {
                if (just_pressed == i) {
                    just_pressed=0;
                    return true;
                } else {
                    return false;
                }
            }

            int press() {
                return just_pressed;
            }

            bool any() {
                const bool something_pressed = (just_pressed != 0) || (pad::just_pressed != -1);
                just_pressed=0;
                pad::just_pressed=-1;
                return something_pressed;
            }

            void text(const bool enable) {
                if (enable)
                    SDL_StartTextInput(backend::video::window);
                else
                    SDL_StopTextInput(backend::video::window);
            }

            const char *utf8char() {
                return has_text_input ? text_input_buffer : nullptr;
            }
        }

        namespace mouse
        {
            int x, y, w;
            uint32_t buttons;
            uint8_t just_pressed = 0;
            bool double_click = false;
            bool discard_buttons = false;

            int posx() {
                return x - mini::view::state.origin[0];
            }

            int posy() {
                return y - mini::view::state.origin[1];
            }

            int wheel() {
                return w;
            }

            bool down(uint8_t i) {
                if (discard_buttons) return false;
                return buttons & SDL_BUTTON_MASK(i);
            }

            bool press(uint8_t i) {
                return just_pressed == i;
            }

            bool dblclick() {
                return double_click;
            }

            void discard() {
                discard_buttons = true;
            }

            bool inside(int x, int y, int w, int h) {
                const int mx = x - mini::view::state.origin[0];
                const int my = y - mini::view::state.origin[1];
                return (mx>=x) && (my>=y) && (mx<x+w) && (my<y+h);
            }

        }

        namespace pad
        {
            SDL_Gamepad *gamepad = nullptr;
            int8_t just_pressed = -1;

            void init() {
                int num_joysticks;
                SDL_JoystickID *joysticks = SDL_GetJoysticks(&num_joysticks);
                if (joysticks) {
                    for (int i=0; i<num_joysticks; ++i) {
                        if (SDL_IsGamepad(joysticks[i])) {
                            gamepad = SDL_OpenGamepad(joysticks[i]);
                            if (SDL_GamepadConnected(gamepad)) {
                                SDL_SetGamepadEventsEnabled(true);
                                // [TODO]
                                //log_msg(LOG_OK, "Gamepad found and initialized");
                                return;
                            }
                        }
                    }
                }
            }

            bool down(int8_t i) {
                if (!gamepad) return false;
                return SDL_GetGamepadButton(gamepad, SDL_GamepadButton(i)) == 1;
            }

            bool press(int8_t i) {
                if (just_pressed == i) {
                    just_pressed = -1;
                    return true;
                } else {
                    return false;
                }
            }

            int press() {
                return just_pressed;
            }
        }
    }
}

#endif
