// spawn_controller.cpp - Implementació del controlador de spawn
// © 2025 Orni Attack

#include "spawn_controller.hpp"

#include <cstdlib>
#include <iostream>

namespace StageSystem {

SpawnController::SpawnController()
    : config_(nullptr),
      temps_transcorregut_(0.0f),
      index_spawn_actual_(0),
      ship_position_(nullptr) {}

void SpawnController::configurar(const ConfigStage* config) {
    config_ = config;
}

void SpawnController::iniciar() {
    if (!config_) {
        std::cerr << "[SpawnController] Error: config_ és null" << std::endl;
        return;
    }

    reset();
    generar_spawn_events();

    std::cout << "[SpawnController] Stage " << static_cast<int>(config_->stage_id)
              << ": generats " << spawn_queue_.size() << " spawn events" << std::endl;
}

void SpawnController::reset() {
    spawn_queue_.clear();
    temps_transcorregut_ = 0.0f;
    index_spawn_actual_ = 0;
}

void SpawnController::actualitzar(float delta_time, std::array<Enemic, 15>& orni_array, bool pausar) {
    if (!config_ || spawn_queue_.empty()) {
        return;
    }

    // Increment timer only when not paused
    if (!pausar) {
        temps_transcorregut_ += delta_time;
    }

    // Process spawn events
    while (index_spawn_actual_ < spawn_queue_.size()) {
        SpawnEvent& event = spawn_queue_[index_spawn_actual_];

        if (event.spawnejat) {
            index_spawn_actual_++;
            continue;
        }

        if (temps_transcorregut_ >= event.temps_spawn) {
            // Find first inactive enemy
            for (auto& enemic : orni_array) {
                if (!enemic.esta_actiu()) {
                    spawn_enemic(enemic, event.tipus, ship_position_);
                    event.spawnejat = true;
                    index_spawn_actual_++;
                    break;
                }
            }

            // If no slot available, try next frame
            if (!event.spawnejat) {
                break;
            }
        } else {
            // Not yet time for this spawn
            break;
        }
    }
}

bool SpawnController::tots_enemics_spawnejats() const {
    return index_spawn_actual_ >= spawn_queue_.size();
}

bool SpawnController::tots_enemics_destruits(const std::array<Enemic, 15>& orni_array) const {
    if (!tots_enemics_spawnejats()) {
        return false;
    }

    for (const auto& enemic : orni_array) {
        if (enemic.esta_actiu()) {
            return false;
        }
    }

    return true;
}

uint8_t SpawnController::get_enemics_vius(const std::array<Enemic, 15>& orni_array) const {
    uint8_t count = 0;
    for (const auto& enemic : orni_array) {
        if (enemic.esta_actiu()) {
            count++;
        }
    }
    return count;
}

uint8_t SpawnController::get_enemics_spawnejats() const {
    return static_cast<uint8_t>(index_spawn_actual_);
}

void SpawnController::generar_spawn_events() {
    if (!config_) {
        return;
    }

    for (uint8_t i = 0; i < config_->total_enemics; i++) {
        float spawn_time = config_->config_spawn.delay_inicial +
            (i * config_->config_spawn.interval_spawn);

        TipusEnemic tipus = seleccionar_tipus_aleatori();

        spawn_queue_.push_back({spawn_time, tipus, false});
    }
}

TipusEnemic SpawnController::seleccionar_tipus_aleatori() const {
    if (!config_) {
        return TipusEnemic::PENTAGON;
    }

    // Weighted random selection based on distribution
    int rand_val = std::rand() % 100;

    if (rand_val < config_->distribucio.pentagon) {
        return TipusEnemic::PENTAGON;
    } else if (rand_val < config_->distribucio.pentagon + config_->distribucio.quadrat) {
        return TipusEnemic::QUADRAT;
    } else {
        return TipusEnemic::MOLINILLO;
    }
}

void SpawnController::spawn_enemic(Enemic& enemic, TipusEnemic tipus, const Punt* ship_pos) {
    // Initialize enemy (with safe spawn if ship_pos provided)
    enemic.inicialitzar(tipus, ship_pos);

    // Apply difficulty multipliers
    aplicar_multiplicadors(enemic);
}

void SpawnController::aplicar_multiplicadors(Enemic& enemic) const {
    if (!config_) {
        return;
    }

    // Apply velocity multiplier
    float base_vel = enemic.get_base_velocity();
    enemic.set_velocity(base_vel * config_->multiplicadors.velocitat);

    // Apply rotation multiplier
    float base_rot = enemic.get_base_rotation();
    enemic.set_rotation(base_rot * config_->multiplicadors.rotacio);

    // Apply tracking strength (only affects QUADRAT)
    enemic.set_tracking_strength(config_->multiplicadors.tracking_strength);
}

}  // namespace StageSystem
