// bala.cpp - Implementació de projectils de la nau
// © 1999 Visente i Sergi (versió Pascal)
// © 2025 Port a C++20 amb SDL3

#include "game/entities/bala.hpp"

#include <algorithm>
#include <cmath>
#include <iostream>

#include "core/audio/audio.hpp"
#include "core/defaults.hpp"
#include "core/graphics/shape_loader.hpp"
#include "core/rendering/shape_renderer.hpp"
#include "game/constants.hpp"

Bala::Bala(SDL_Renderer* renderer)
    : renderer_(renderer),
      centre_({.x = 0.0F, .y = 0.0F}),
      angle_(0.0F),
      velocitat_(0.0F),
      esta_(false),
      grace_timer_(0.0F),
      brightness_(Defaults::Brightness::BALA) {
    // [NUEVO] Carregar forma compartida des de fitxer
    forma_ = Graphics::ShapeLoader::load("bullet.shp");

    if (!forma_ || !forma_->es_valida()) {
        std::cerr << "[Bala] Error: no s'ha pogut carregar bullet.shp" << std::endl;
    }
}

void Bala::inicialitzar() {
    // Inicialment inactiva
    esta_ = false;
    centre_ = {.x = 0.0F, .y = 0.0F};
    angle_ = 0.0F;
    velocitat_ = 0.0F;
    grace_timer_ = 0.0F;
}

void Bala::disparar(const Punt& posicio, float angle, uint8_t owner_id) {
    // Activar bala i posicionar-la a la nau
    // Basat en joc_asteroides.cpp línies 188-200

    // Activar bala
    esta_ = true;

    // Posició inicial = centre de la nau
    centre_.x = posicio.x;
    centre_.y = posicio.y;

    // Angle = angle de la nau (dispara en la direcció que apunta)
    angle_ = angle;

    // Almacenar propietario (0=P1, 1=P2)
    owner_id_ = owner_id;

    // Velocitat alta (el joc Pascal original usava 7 px/frame)
    // 7 px/frame × 20 FPS = 140 px/s
    velocitat_ = 140.0F;

    // Activar grace period (prevents instant self-collision)
    grace_timer_ = Defaults::Game::BULLET_GRACE_PERIOD;

    // Reproducir sonido de disparo láser
    Audio::get()->playSound(Defaults::Sound::LASER, Audio::Group::GAME);
}

void Bala::actualitzar(float delta_time) {
    if (esta_) {
        // Decrementar grace timer
        if (grace_timer_ > 0.0F) {
            grace_timer_ -= delta_time;
            grace_timer_ = std::max(grace_timer_, 0.0F);
        }

        mou(delta_time);
    }
}

void Bala::dibuixar() const {
    if (esta_ && forma_) {
        // [NUEVO] Usar render_shape en lloc de rota_pol
        // Les bales roten segons l'angle de trajectòria
        Rendering::render_shape(renderer_, forma_, centre_, angle_, 1.0F, true, 1.0F, brightness_);
    }
}

void Bala::mou(float delta_time) {
    // Moviment rectilini de la bala
    // Basat en el codi Pascal original: procedure mou_bales
    // Copiat EXACTAMENT de joc_asteroides.cpp línies 396-419

    // Calcular nova posició (moviment polar time-based)
    // velocitat ja està en px/s (140 px/s), només cal multiplicar per delta_time
    float velocitat_efectiva = velocitat_ * delta_time;

    // Calcular desplaçament (angle-PI/2 perquè angle=0 apunta amunt)
    float dy = velocitat_efectiva * std::sin(angle_ - (Constants::PI / 2.0F));
    float dx = velocitat_efectiva * std::cos(angle_ - (Constants::PI / 2.0F));

    // Acumulació directa amb precisió subpíxel
    centre_.y += dy;
    centre_.x += dx;

    // Desactivar si surt de la zona de joc (no rebota com els ORNIs)
    // CORRECCIÓ: Usar límits segurs amb radi de la bala
    float min_x;
    float max_x;
    float min_y;
    float max_y;
    Constants::obtenir_limits_zona_segurs(Defaults::Entities::BULLET_RADIUS,
        min_x,
        max_x,
        min_y,
        max_y);

    if (centre_.x < min_x || centre_.x > max_x ||
        centre_.y < min_y || centre_.y > max_y) {
        esta_ = false;
    }
}
