// escena_joc.cpp - Implementació de la lògica del joc
// © 1999 Visente i Sergi (versió Pascal)
// © 2025 Port a C++20 amb SDL3

#include "escena_joc.hpp"
#include "../../core/rendering/line_renderer.hpp"
#include "../../core/system/gestor_escenes.hpp"
#include "../../core/system/global_events.hpp"
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <vector>

EscenaJoc::EscenaJoc(SDLManager &sdl)
    : sdl_(sdl), debris_manager_(sdl.obte_renderer()),
      nau_(sdl.obte_renderer()), itocado_(0), text_(sdl.obte_renderer()) {
  // Inicialitzar bales amb renderer
  for (auto &bala : bales_) {
    bala = Bala(sdl.obte_renderer());
  }

  // Inicialitzar enemics amb renderer
  for (auto &enemy : orni_) {
    enemy = Enemic(sdl.obte_renderer());
  }
}

void EscenaJoc::executar() {
  std::cout << "Escena Joc: Inicialitzant...\n";

  // Inicialitzar estat del joc
  inicialitzar();

  SDL_Event event;
  Uint64 last_time = SDL_GetTicks();

  while (GestorEscenes::actual == GestorEscenes::Escena::JOC) {
    // Calcular delta_time real
    Uint64 current_time = SDL_GetTicks();
    float delta_time = (current_time - last_time) / 1000.0f;
    last_time = current_time;

    // Limitar delta_time per evitar grans salts
    if (delta_time > 0.05f) {
      delta_time = 0.05f;
    }

    // Processar events SDL
    while (SDL_PollEvent(&event)) {
      // Manejo de finestra
      if (sdl_.handleWindowEvent(event)) {
        continue;
      }

      // Events globals (F1/F2/F3/ESC/QUIT)
      if (GlobalEvents::handle(event, sdl_)) {
        continue;
      }

      // Processament específic del joc (SPACE per disparar)
      processar_input(event);
    }

    // Actualitzar física del joc amb delta_time real
    actualitzar(delta_time);

    // Actualitzar colors oscil·lats
    sdl_.updateColors(delta_time);

    // Netejar pantalla (usa color oscil·lat)
    sdl_.neteja(0, 0, 0);

    // Dibuixar joc
    dibuixar();

    // Presentar renderer (swap buffers)
    sdl_.presenta();
  }

  std::cout << "Escena Joc: Finalitzant...\n";
}

void EscenaJoc::inicialitzar() {
  // Inicialitzar generador de números aleatoris
  // Basat en el codi Pascal original: line 376
  std::srand(static_cast<unsigned>(std::time(nullptr)));

  // Inicialitzar estat de col·lisió
  itocado_ = 0;

  // Inicialitzar nau
  nau_.inicialitzar();

  // Inicialitzar enemics (ORNIs)
  for (auto &enemy : orni_) {
    enemy.inicialitzar();
  }

  // Inicialitzar bales
  for (auto &bala : bales_) {
    bala.inicialitzar();
  }
}

void EscenaJoc::actualitzar(float delta_time) {
  // Actualitzar nau (input + física)
  nau_.processar_input(delta_time);
  nau_.actualitzar(delta_time);

  // Actualitzar moviment i rotació dels enemics (ORNIs)
  for (auto &enemy : orni_) {
    enemy.actualitzar(delta_time);
  }

  // Actualitzar moviment de bales (Fase 9)
  for (auto &bala : bales_) {
    bala.actualitzar(delta_time);
  }

  // Actualitzar fragments d'explosions
  debris_manager_.actualitzar(delta_time);
}

void EscenaJoc::dibuixar() {
  // Dibuixar marges de la zona de joc
  dibuixar_marges();

  // Dibuixar nau
  nau_.dibuixar();

  // Dibuixar ORNIs (enemics)
  for (const auto &enemy : orni_) {
    enemy.dibuixar();
  }

  // Dibuixar bales (Fase 9)
  for (const auto &bala : bales_) {
    bala.dibuixar();
  }

  // Dibuixar fragments d'explosions (després d'altres objectes)
  debris_manager_.dibuixar();

  // Dibuixar marcador
  dibuixar_marcador();
}

void EscenaJoc::processar_input(const SDL_Event &event) {
  // Processament d'input per events puntuals (no continus)
  // L'input continu (fletxes) es processa en actualitzar() amb
  // SDL_GetKeyboardState()

  if (event.type == SDL_EVENT_KEY_DOWN) {
    switch (event.key.key) {
    case SDLK_SPACE: {
      // TEMPORAL: Explotar enemic aleatori (per testing)
      // TODO: Restaurar dispars quan el sistema d'explosions estiga validat

      // Buscar tots els enemics actius
      std::vector<int> enemics_actius;
      for (int i = 0; i < Constants::MAX_ORNIS; i++) {
        if (orni_[i].esta_actiu()) {
          enemics_actius.push_back(i);
        }
      }

      if (!enemics_actius.empty()) {
        // Seleccionar enemic aleatori
        int idx = enemics_actius[std::rand() % enemics_actius.size()];

        // Crear explosió
        debris_manager_.explotar(orni_[idx].get_forma(),
                                 orni_[idx].get_centre(),
                                 0.0f, // angle (enemics no roten físicament)
                                 1.0f, // escala
                                 Defaults::Physics::Debris::VELOCITAT_BASE);

        // Desactivar enemic
        orni_[idx].destruir();

        std::cout << "[TEST] Enemic " << idx << " explotat!\n";
      }
      break;
    }

    default:
      break;
    }
  }
}

void EscenaJoc::tocado() {
  // TODO: Implementar seqüència de mort
}

void EscenaJoc::dibuixar_marges() const {
  // Dibuixar rectangle de la zona de joc
  const SDL_FRect &zona = Defaults::Zones::PLAYAREA;

  // Coordenades dels cantons
  int x1 = static_cast<int>(zona.x);
  int y1 = static_cast<int>(zona.y);
  int x2 = static_cast<int>(zona.x + zona.w);
  int y2 = static_cast<int>(zona.y + zona.h);

  // 4 línies per formar el rectangle
  Rendering::linea(sdl_.obte_renderer(), x1, y1, x2, y1, true); // Top
  Rendering::linea(sdl_.obte_renderer(), x1, y2, x2, y2, true); // Bottom
  Rendering::linea(sdl_.obte_renderer(), x1, y1, x1, y2, true); // Left
  Rendering::linea(sdl_.obte_renderer(), x2, y1, x2, y2, true); // Right
}

void EscenaJoc::dibuixar_marcador() {
  // Text estàtic (hardcoded)
  const std::string text = "SCORE: 01000  LIFE: 3  LEVEL: 01";

  // Paràmetres de renderització
  const float escala = 0.85f;
  const float spacing = 0.0f;

  // Calcular dimensions del text
  float text_width = text_.get_text_width(text, escala, spacing);
  float text_height = text_.get_text_height(escala);

  // Centrat horitzontal dins de la zona del marcador
  float x = (Defaults::Zones::SCOREBOARD.w - text_width) / 2.0f;

  // Centrat vertical dins de la zona del marcador
  float y = Defaults::Zones::SCOREBOARD.y +
            (Defaults::Zones::SCOREBOARD.h - text_height) / 2.0f;

  // Renderitzar
  text_.render(text, {x, y}, escala, spacing);
}
