// escena_logo.cpp - Implementació de l'escena logo
// © 2025 Port a C++20

#include "escena_logo.hpp"
#include "../../core/graphics/shape_loader.hpp"
#include "../../core/rendering/shape_renderer.hpp"
#include "../../core/system/gestor_escenes.hpp"
#include "../../core/system/global_events.hpp"
#include <algorithm>
#include <cfloat>
#include <iostream>

// Helper: calcular el progrés individual d'una lletra
// en funció del progrés global (efecte seqüencial)
static float calcular_progress_letra(size_t letra_index, size_t num_letras,
                                     float global_progress, float threshold) {
  if (num_letras == 0)
    return 1.0f;

  // Calcular temps per lletra
  float duration_per_letra = 1.0f / static_cast<float>(num_letras);
  float step = threshold * duration_per_letra;
  float start = static_cast<float>(letra_index) * step;
  float end = start + duration_per_letra;

  // Interpolar progrés
  if (global_progress < start) {
    return 0.0f; // Encara no ha començat
  } else if (global_progress >= end) {
    return 1.0f; // Completament apareguda
  } else {
    return (global_progress - start) / (end - start);
  }
}

EscenaLogo::EscenaLogo(SDLManager &sdl)
    : sdl_(sdl), estat_actual_(EstatAnimacio::PRE_ANIMATION),
      temps_estat_actual_(0.0f) {
  std::cout << "Escena Logo: Inicialitzant...\n";
  inicialitzar_lletres();
}

void EscenaLogo::executar() {
  SDL_Event event;
  Uint64 last_time = SDL_GetTicks();

  while (GestorEscenes::actual == GestorEscenes::Escena::LOGO) {
    // 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;
      }

      // Processar events de l'escena (qualsevol tecla/clic salta al joc)
      processar_events(event);
    }

    // Actualitzar lògica
    actualitzar(delta_time);

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

    // Dibuixar
    dibuixar();
  }

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

void EscenaLogo::inicialitzar_lletres() {
  using namespace Graphics;

  // Llista de fitxers .shp (A repetida per a les dues A's)
  std::vector<std::string> fitxers = {
      "logo/letra_j.shp", "logo/letra_a.shp", "logo/letra_i.shp",
      "logo/letra_l.shp", "logo/letra_g.shp", "logo/letra_a.shp",
      "logo/letra_m.shp", "logo/letra_e.shp", "logo/letra_s.shp"};

  // Pas 1: Carregar totes les formes i calcular amplades
  float ancho_total = 0.0f;

  for (const auto &fitxer : fitxers) {
    auto forma = ShapeLoader::load(fitxer);
    if (!forma || !forma->es_valida()) {
      std::cerr << "[EscenaLogo] Error carregant " << fitxer << std::endl;
      continue;
    }

    // Calcular bounding box de la forma (trobar ancho)
    float min_x = FLT_MAX;
    float max_x = -FLT_MAX;

    for (const auto &prim : forma->get_primitives()) {
      for (const auto &punt : prim.points) {
        min_x = std::min(min_x, punt.x);
        max_x = std::max(max_x, punt.x);
      }
    }

    float ancho_sin_escalar = max_x - min_x;

    // IMPORTANT: Escalar ancho i offset amb ESCALA_FINAL
    // per que les posicions finals coincideixin amb la mida real de les lletres
    float ancho = ancho_sin_escalar * ESCALA_FINAL;
    float offset_centre = (forma->get_centre().x - min_x) * ESCALA_FINAL;

    lletres_.push_back({forma,
                        {0.0f, 0.0f}, // Posició es calcularà després
                        ancho,
                        offset_centre});

    ancho_total += ancho;
  }

  // Pas 2: Afegir espaiat entre lletres
  ancho_total += ESPAI_ENTRE_LLETRES * (lletres_.size() - 1);

  // Pas 3: Calcular posició inicial (centrat horitzontal)
  constexpr float PANTALLA_ANCHO = 640.0f;
  constexpr float PANTALLA_ALTO = 480.0f;

  float x_inicial = (PANTALLA_ANCHO - ancho_total) / 2.0f;
  float y_centre = PANTALLA_ALTO / 2.0f;

  // Pas 4: Assignar posicions a cada lletra
  float x_actual = x_inicial;

  for (auto &lletra : lletres_) {
    // Posicionar el centre de la forma (shape_centre) en pantalla
    // Usar offset_centre en lloc de ancho/2 perquè shape_centre
    // pot no estar exactament al mig del bounding box
    lletra.posicio.x = x_actual + lletra.offset_centre;
    lletra.posicio.y = y_centre;

    // Avançar per a següent lletra
    x_actual += lletra.ancho + ESPAI_ENTRE_LLETRES;
  }

  std::cout << "[EscenaLogo] " << lletres_.size()
            << " lletres carregades, ancho total: " << ancho_total << " px\n";
}

void EscenaLogo::canviar_estat(EstatAnimacio nou_estat) {
  estat_actual_ = nou_estat;
  temps_estat_actual_ = 0.0f; // Reset temps
  std::cout << "[EscenaLogo] Canvi a estat: " << static_cast<int>(nou_estat)
            << "\n";
}

bool EscenaLogo::totes_lletres_completes() const {
  // Quan global_progress = 1.0, totes les lletres tenen letra_progress = 1.0
  return temps_estat_actual_ >= DURACIO_ZOOM;
}

void EscenaLogo::actualitzar(float delta_time) {
  temps_estat_actual_ += delta_time;

  switch (estat_actual_) {
  case EstatAnimacio::PRE_ANIMATION:
    if (temps_estat_actual_ >= DURACIO_PRE) {
      canviar_estat(EstatAnimacio::ANIMATION);
    }
    break;

  case EstatAnimacio::ANIMATION:
    if (totes_lletres_completes()) {
      canviar_estat(EstatAnimacio::POST_ANIMATION);
    }
    break;

  case EstatAnimacio::POST_ANIMATION:
    if (temps_estat_actual_ >= DURACIO_POST) {
      GestorEscenes::actual = GestorEscenes::Escena::JOC;
    }
    break;
  }
}

void EscenaLogo::dibuixar() {
  // Fons negre
  sdl_.neteja(0, 0, 0);

  // PRE_ANIMATION: Només pantalla negra
  if (estat_actual_ == EstatAnimacio::PRE_ANIMATION) {
    sdl_.presenta();
    return; // No renderitzar lletres
  }

  // ANIMATION o POST_ANIMATION: Calcular progrés
  float global_progress =
      (estat_actual_ == EstatAnimacio::ANIMATION)
          ? std::min(temps_estat_actual_ / DURACIO_ZOOM, 1.0f)
          : 1.0f; // POST: mantenir al 100%

  // Punt inicial del zoom (configurable amb ORIGEN_ZOOM_X/Y)
  const Punt ORIGEN_ZOOM = {ORIGEN_ZOOM_X, ORIGEN_ZOOM_Y};

  // Dibuixar cada lletra amb animació seqüencial
  for (size_t i = 0; i < lletres_.size(); i++) {
    const auto &lletra = lletres_[i];

    // Calcular progrés individual d'aquesta lletra (0.0 → 1.0)
    float letra_progress = calcular_progress_letra(
        i, lletres_.size(), global_progress, THRESHOLD_LETRA);

    // Si la lletra encara no ha començat, saltar-la
    if (letra_progress <= 0.0f) {
      continue;
    }

    // Interpolar posició: des del origen zoom cap a posició final
    Punt pos_actual;
    pos_actual.x =
        ORIGEN_ZOOM.x + (lletra.posicio.x - ORIGEN_ZOOM.x) * letra_progress;
    pos_actual.y =
        ORIGEN_ZOOM.y + (lletra.posicio.y - ORIGEN_ZOOM.y) * letra_progress;

    // Aplicar ease-out quadràtic per suavitat
    float t = letra_progress;
    float ease_factor = 1.0f - (1.0f - t) * (1.0f - t);

    // Interpolar escala amb ease-out: des de ESCALA_INICIAL cap a ESCALA_FINAL
    float escala_actual =
        ESCALA_INICIAL + (ESCALA_FINAL - ESCALA_INICIAL) * ease_factor;

    // Renderitzar la lletra
    Rendering::render_shape(
        sdl_.obte_renderer(), lletra.forma,
        pos_actual,    // Posició interpolada
        0.0f,          // Sense rotació
        escala_actual, // Escala interpolada amb ease-out
        true,          // Dibuixar
        1.0f // Progress = 1.0 (lletra completa, sense animació de primitives)
    );
  }

  sdl_.presenta();
}

void EscenaLogo::processar_events(const SDL_Event &event) {
  // Qualsevol tecla o clic de ratolí salta al joc
  if (event.type == SDL_EVENT_KEY_DOWN ||
      event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
    GestorEscenes::actual = GestorEscenes::Escena::JOC;
  }
}
