#if BACKEND == SDL3

#include "backends/backend.h"
#include "state.h"
#include "mini/win/win.h"
#include "mini/surf/surf.h"
#include "mini/pal/pal.h"
#include "mini/shader/shader.h"

namespace backend
{
    namespace video
    {
        SDL_Window      *window         { nullptr };
        SDL_Renderer    *renderer       { nullptr };
        SDL_Texture     *tex_back       { nullptr };
        SDL_Texture     *tex_shader     { nullptr };

        void init() {
            const auto &title = mini::win::state.title;
            const auto &width = mini::win::state.width;
            const auto &height = mini::win::state.height;
            auto &zoom = mini::win::state.zoom;

            // Ajustar el zoom a un valor vàlid
            if (zoom <= 0) zoom = 1;
            const SDL_DisplayMode *dm = SDL_GetDesktopDisplayMode(SDL_GetPrimaryDisplay());
            while ( width * zoom > dm->w || height * zoom > dm->h) zoom--;

            // Crear SDL_Window i SDL_Renderer
            window = SDL_CreateWindow(title, width*zoom, height*zoom, SDL_WINDOW_OPENGL|(mini::win::state.fullscreen?SDL_WINDOW_FULLSCREEN:0));
            SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
            renderer = SDL_CreateRenderer(window, NULL);
            SDL_SetRenderVSync(renderer, SDL_RENDERER_VSYNC_DISABLED);

            // Mostrar o ocultar el cursor
            if (mini::win::state.cursor) SDL_ShowCursor(); else SDL_HideCursor();

            // Crear textura backbuffer
            tex_back = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height);
            SDL_SetTextureScaleMode(tex_back, SDL_SCALEMODE_NEAREST);

            // Crear textura shaders i inicialitzar shaders
            tex_shader = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, width*zoom, height*zoom);
            SDL_SetTextureScaleMode(tex_shader, SDL_SCALEMODE_NEAREST);
            
            mini::shader::init(window, tex_shader, nullptr);
            
            // [TODO]
            //log_msg(LOG_OK, "Graphics subsystem initialized\n");
        }

        void quit() {
            SDL_DestroyTexture(tex_shader);
            SDL_DestroyTexture(tex_back);
            SDL_DestroyRenderer(renderer);
            SDL_DestroyWindow(window);
        }

        void render() {
            // Render frame
            SDL_SetRenderTarget(renderer, tex_shader);
            //SDL_SetRenderDrawColor(win::state.renderer, 0, 0, 0, 255);
            //SDL_RenderClear(win::state.renderer);

            uint32_t *pixels;
            int pitch;
            SDL_LockTexture(tex_back, NULL, (void**)&pixels, &pitch);
            auto &s = mini::surf::state.surfaces[SCREEN];
            uint8_t *p = s.p;
            for (uint32_t i=0;i<s.size;++i) pixels[i] = mini::pal::palette[p[i]];
            SDL_UnlockTexture(tex_back);
            SDL_RenderTexture(renderer, tex_back, NULL, NULL); //NEW

            mini::shader::render();

            //SDL_RenderTexture(mini_ren, mini_bak, NULL, NULL);
            //SDL_RenderPresent(mini_ren);
        }

        void raise_window() {
            SDL_RaiseWindow(window);
        }

        void cursor(const bool value) {
            if (value) SDL_ShowCursor(); else SDL_HideCursor();
        }
    }
}

#endif
