#include "core/screen.hpp"

#include <iostream>

#include "game/defines.hpp"
#include "game/options.hpp"

Screen* Screen::instance_ = nullptr;

void Screen::init() {
    instance_ = new Screen();
}

void Screen::destroy() {
    delete instance_;
    instance_ = nullptr;
}

auto Screen::get() -> Screen* {
    return instance_;
}

Screen::Screen() {
    // Carrega opcions guardades
    zoom_ = Options::window.zoom;
    fullscreen_ = Options::window.fullscreen;

    calculateMaxZoom();

    if (zoom_ < 1) zoom_ = 1;
    if (zoom_ > max_zoom_) zoom_ = max_zoom_;

    int w = GAME_WIDTH * zoom_;
    int h = GAME_HEIGHT * zoom_;

    window_ = SDL_CreateWindow(Texts::WINDOW_TITLE, w, h, fullscreen_ ? SDL_WINDOW_FULLSCREEN : 0);
    renderer_ = SDL_CreateRenderer(window_, nullptr);
    SDL_SetRenderLogicalPresentation(renderer_, GAME_WIDTH, GAME_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX);

    texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, GAME_WIDTH, GAME_HEIGHT);
    SDL_SetTextureScaleMode(texture_, SDL_SCALEMODE_NEAREST);

    std::cout << "Screen initialized: " << w << "x" << h << " (zoom " << zoom_ << ", max " << max_zoom_ << ")\n";
}

Screen::~Screen() {
    // Guarda opcions abans de destruir
    Options::window.zoom = zoom_;
    Options::window.fullscreen = fullscreen_;

    if (texture_) SDL_DestroyTexture(texture_);
    if (renderer_) SDL_DestroyRenderer(renderer_);
    if (window_) SDL_DestroyWindow(window_);
}

void Screen::present(const Uint32* pixel_data) {
    SDL_UpdateTexture(texture_, nullptr, pixel_data, GAME_WIDTH * sizeof(Uint32));
    SDL_RenderClear(renderer_);
    SDL_RenderTexture(renderer_, texture_, nullptr, nullptr);
    SDL_RenderPresent(renderer_);
}

void Screen::toggleFullscreen() {
    fullscreen_ = !fullscreen_;
    SDL_SetWindowFullscreen(window_, fullscreen_);
    if (!fullscreen_) {
        adjustWindowSize();
    }
    std::cout << (fullscreen_ ? "Fullscreen ON\n" : "Fullscreen OFF\n");
}

void Screen::incZoom() {
    if (fullscreen_ || zoom_ >= max_zoom_) return;
    zoom_++;
    adjustWindowSize();
}

void Screen::decZoom() {
    if (fullscreen_ || zoom_ <= 1) return;
    zoom_--;
    adjustWindowSize();
}

void Screen::setZoom(int zoom) {
    if (zoom < 1 || zoom > max_zoom_ || fullscreen_) return;
    zoom_ = zoom;
    adjustWindowSize();
}

void Screen::adjustWindowSize() {
    int w = GAME_WIDTH * zoom_;
    int h = GAME_HEIGHT * zoom_;
    SDL_SetWindowSize(window_, w, h);
    SDL_SetWindowPosition(window_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
}

void Screen::calculateMaxZoom() {
    SDL_DisplayID display = SDL_GetPrimaryDisplay();
    const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(display);
    if (mode) {
        int max_w = mode->w / GAME_WIDTH;
        int max_h = mode->h / GAME_HEIGHT;
        max_zoom_ = (max_w < max_h) ? max_w : max_h;
        if (max_zoom_ < 1) max_zoom_ = 1;
    }
}
