#include "engine/renderer.h"
#include "engine/camera.h"
#include "config.h"
#include <string.h>

static SDL_Renderer *s_renderer;

static Sprite s_queue[MAX_SPRITES];
static int    s_queue_count;
static SDL_Color s_clear_color = {30, 30, 46, 255}; /* default dark blue */

void renderer_init(SDL_Renderer *r) {
    s_renderer = r;
    s_queue_count = 0;
}

void renderer_set_clear_color(SDL_Color color) {
    s_clear_color = color;
}

void renderer_clear(void) {
    SDL_SetRenderDrawColor(s_renderer,
        s_clear_color.r, s_clear_color.g, s_clear_color.b, s_clear_color.a);
    SDL_RenderClear(s_renderer);
    s_queue_count = 0;
}

void renderer_submit(const Sprite *sprite) {
    if (s_queue_count >= MAX_SPRITES) return;
    s_queue[s_queue_count++] = *sprite;
}

void renderer_flush(const Camera *cam) {
    /* Draw sprites layer by layer */
    for (int layer = 0; layer < LAYER_COUNT; layer++) {
        for (int i = 0; i < s_queue_count; i++) {
            Sprite *s = &s_queue[i];
            if ((int)s->layer != layer) continue;

            /* Convert world to screen coords (HUD stays in screen space) */
            Vec2 screen_pos = s->pos;
            if (layer != LAYER_HUD && cam) {
                screen_pos = camera_world_to_screen(cam, s->pos);
            }

            float zw = s->size.x;
            float zh = s->size.y;
            if (layer != LAYER_HUD && cam && cam->zoom != 1.0f && cam->zoom > 0.0f) {
                zw *= cam->zoom;
                zh *= cam->zoom;
            }

            SDL_Rect dst = {
                (int)screen_pos.x,
                (int)screen_pos.y,
                (int)(zw + 0.5f),
                (int)(zh + 0.5f)
            };

            SDL_RendererFlip flip = SDL_FLIP_NONE;
            if (s->flip_x) flip |= SDL_FLIP_HORIZONTAL;
            if (s->flip_y) flip |= SDL_FLIP_VERTICAL;

            if (s->alpha < 255) {
                SDL_SetTextureAlphaMod(s->texture, s->alpha);
            }

            SDL_RenderCopyEx(s_renderer, s->texture, &s->src, &dst,
                             s->rotation, NULL, flip);

            if (s->alpha < 255) {
                SDL_SetTextureAlphaMod(s->texture, 255);
            }
        }
    }
}

void renderer_present(void) {
    SDL_RenderPresent(s_renderer);
}

void renderer_draw_rect(Vec2 pos, Vec2 size, SDL_Color color,
                         DrawLayer layer, const Camera *cam) {
    Vec2 screen_pos = pos;
    float zw = size.x, zh = size.y;
    if (layer != LAYER_HUD && cam) {
        screen_pos = camera_world_to_screen(cam, pos);
        if (cam->zoom != 1.0f && cam->zoom > 0.0f) {
            zw *= cam->zoom;
            zh *= cam->zoom;
        }
    }

    SDL_Rect rect = {
        (int)screen_pos.x,
        (int)screen_pos.y,
        (int)(zw + 0.5f),
        (int)(zh + 0.5f)
    };

    SDL_SetRenderDrawColor(s_renderer, color.r, color.g, color.b, color.a);
    SDL_RenderFillRect(s_renderer, &rect);
}

void renderer_shutdown(void) {
    s_queue_count = 0;
}
