#include "game/gameplay/scoreboard.hpp"

#include <SDL3/SDL.h>

#include <string>
#include <utility>
#include <vector>

#include "core/locale/locale.hpp"
#include "core/rendering/screen.hpp"
#include "core/rendering/surface.hpp"
#include "core/rendering/text.hpp"
#include "core/resources/resource_cache.hpp"
#include "game/options.hpp"
#include "utils/defines.hpp"

// Constructor
Scoreboard::Scoreboard(std::shared_ptr<Data> data)
    : data_(std::move(data)),
      surface_(std::make_shared<Surface>(Options::game.width, SURFACE_HEIGHT)),
      surface_dest_{.x = 0, .y = Options::game.height - SURFACE_HEIGHT, .w = Options::game.width, .h = SURFACE_HEIGHT} {}

// Pinta el objeto en pantalla
void Scoreboard::render() {
    surface_->render(nullptr, &surface_dest_);
}

// Actualiza las variables del objeto
void Scoreboard::update(float delta_time) {
    fillTexture();

    if (!is_paused_) {
        clock_ = getTime();
    }
}

// Obtiene el tiempo transcurrido de partida
auto Scoreboard::getTime() -> Scoreboard::ClockData {
    const Uint32 TIME_ELAPSED = SDL_GetTicks() - data_->ini_clock - paused_time_elapsed_;

    ClockData time;
    time.hours = TIME_ELAPSED / 3600000;
    time.minutes = TIME_ELAPSED / 60000;
    time.seconds = TIME_ELAPSED / 1000;
    time.separator = (TIME_ELAPSED % 1000 <= 500) ? ":" : " ";

    return time;
}

// Pone el marcador en modo pausa
void Scoreboard::setPaused(bool value) {
    if (is_paused_ == value) { return; }
    is_paused_ = value;

    if (is_paused_) {
        paused_time_ = SDL_GetTicks();
    } else {
        paused_time_elapsed_ += SDL_GetTicks() - paused_time_;
    }
}

// Devuelve la cantidad de minutos de juego transcurridos
auto Scoreboard::getMinutes() -> int {
    return getTime().minutes;
}

// Dibuja los elementos del marcador en la surface
void Scoreboard::fillTexture() {
    auto previous_renderer = Screen::get()->getRendererSurface();
    Screen::get()->setRendererSurface(surface_);

    surface_->clear(0);

    auto text = Resource::Cache::get()->getText("8bithud");
    const int CANVAS_W = static_cast<int>(Options::game.width);
    const std::string SEP = " - ";
    const int MONO_W = 7;  // Ancho fijo por carácter monoespaciado (dígitos + separador)

    // Valores formateados
    const std::string LIVES_STR = std::to_string(data_->lives);
    const std::string ITEMS_STR = std::to_string(data_->items);
    const std::string TIME_STR = std::to_string((clock_.minutes % 100) / 10) + std::to_string(clock_.minutes % 10) + clock_.separator + std::to_string((clock_.seconds % 60) / 10) + std::to_string(clock_.seconds % 10);

    // --- Línea 1: vides X - objectes X - temps MM:SS (centrada) ---
    const std::string LIVES_LABEL = Locale::get()->get("scoreboard.lives");
    const std::string ITEMS_LABEL = Locale::get()->get("scoreboard.items");
    const std::string TIME_LABEL = Locale::get()->get("scoreboard.time");

    // Ancho total: labels proporcionales + valores monoespaciados
    const int LINE1_W = text->length(LIVES_LABEL) + Text::lengthMono(LIVES_STR, MONO_W) + text->length(SEP) + text->length(ITEMS_LABEL) + Text::lengthMono(ITEMS_STR, MONO_W) + text->length(SEP) + text->length(TIME_LABEL) + Text::lengthMono(TIME_STR, MONO_W);

    int x = (CANVAS_W - LINE1_W) / 2;
    text->writeColored(x, LINE1_Y, LIVES_LABEL, LABEL_COLOR);
    x += text->length(LIVES_LABEL);
    text->writeColoredMono(x, LINE1_Y, LIVES_STR, VALUE_COLOR, MONO_W);
    x += Text::lengthMono(LIVES_STR, MONO_W);
    text->writeColored(x, LINE1_Y, SEP, LABEL_COLOR);
    x += text->length(SEP);
    text->writeColored(x, LINE1_Y, ITEMS_LABEL, LABEL_COLOR);
    x += text->length(ITEMS_LABEL);
    text->writeColoredMono(x, LINE1_Y, ITEMS_STR, VALUE_COLOR, MONO_W);
    x += Text::lengthMono(ITEMS_STR, MONO_W);
    text->writeColored(x, LINE1_Y, SEP, LABEL_COLOR);
    x += text->length(SEP);
    text->writeColored(x, LINE1_Y, TIME_LABEL, LABEL_COLOR);
    x += text->length(TIME_LABEL);
    text->writeColoredMono(x, LINE1_Y, TIME_STR, VALUE_COLOR, MONO_W);

    // --- Línea 2: indicadores activos (centrada) ---
    std::vector<std::string> indicators;
    if (data_->music) {
        indicators.push_back(Locale::get()->get("scoreboard.music_on"));
    }
    if (Options::cheats.infinite_lives == Options::Cheat::State::ENABLED) {
        indicators.push_back(Locale::get()->get("scoreboard.cheat_infinite_lives"));
    }
    if (Options::cheats.invincible == Options::Cheat::State::ENABLED) {
        indicators.push_back(Locale::get()->get("scoreboard.cheat_invincibility"));
    }

    if (!indicators.empty()) {
        int line2_w = 0;
        for (size_t i = 0; i < indicators.size(); ++i) {
            if (i > 0) { line2_w += text->length(SEP); }
            line2_w += text->length(indicators[i]);
        }
        x = (CANVAS_W - line2_w) / 2;
        for (size_t i = 0; i < indicators.size(); ++i) {
            if (i > 0) {
                text->writeColored(x, LINE2_Y, SEP, LABEL_COLOR);
                x += text->length(SEP);
            }
            text->writeColored(x, LINE2_Y, indicators[i], LABEL_COLOR);
            x += text->length(indicators[i]);
        }
    }

    Screen::get()->setRendererSurface(previous_renderer);
}
