#include "platform_manager.hpp"

#include "game/entities/moving_platform.hpp"  // Para MovingPlatform

// Añade una plataforma a la colección
void PlatformManager::addPlatform(std::shared_ptr<MovingPlatform> platform) {
    platforms_.push_back(std::move(platform));
}

// Elimina todas las plataformas
void PlatformManager::clear() {
    platforms_.clear();
}

// Comprueba si no hay plataformas
auto PlatformManager::isEmpty() const -> bool {
    return platforms_.empty();
}

// Actualiza todas las plataformas
void PlatformManager::update(float delta_time) {
    for (const auto& platform : platforms_) {
        platform->update(delta_time);
    }
}

// Renderiza todas las plataformas
void PlatformManager::render() {
    for (const auto& platform : platforms_) {
        platform->render();
    }
}

#ifdef _DEBUG
// Solo actualiza animaciones sin mover plataformas
void PlatformManager::updateAnimations(float delta_time) {
    for (const auto& platform : platforms_) {
        platform->updateAnimation(delta_time);
    }
}

// Resetea todas las plataformas a su posición inicial
void PlatformManager::resetPositions(const std::vector<MovingPlatform::Data>& platform_data) {
    const int COUNT = std::min(static_cast<int>(platforms_.size()), static_cast<int>(platform_data.size()));
    for (int i = 0; i < COUNT; ++i) {
        platforms_[i]->resetToInitialPosition(platform_data[i]);
    }
}

// Número de plataformas
auto PlatformManager::getCount() const -> int {
    return static_cast<int>(platforms_.size());
}

// Acceso a una plataforma por índice
auto PlatformManager::getPlatform(int index) -> std::shared_ptr<MovingPlatform>& {
    return platforms_.at(index);
}

// Elimina la última plataforma
void PlatformManager::removeLastPlatform() {
    if (!platforms_.empty()) {
        platforms_.pop_back();
    }
}
#endif

// Comprueba si el jugador está sobre alguna plataforma
// Devuelve puntero a la plataforma o nullptr si no está sobre ninguna
auto PlatformManager::checkPlayerOnPlatform(const SDL_FRect& player_collider, float player_vy) -> MovingPlatform* {
    // Solo detectamos si el jugador está cayendo o quieto (no saltando hacia arriba)
    if (player_vy < 0.0F) {
        return nullptr;
    }

    for (const auto& platform : platforms_) {
        SDL_FRect plat_rect = platform->getCollider();

        // Comprobar overlap horizontal
        if (player_collider.x + player_collider.w <= plat_rect.x) { continue; }
        if (player_collider.x >= plat_rect.x + plat_rect.w) { continue; }

        // Comprobar que los pies del jugador están cerca del top de la plataforma
        float player_feet = player_collider.y + player_collider.h;
        float platform_top = plat_rect.y;

        // Tolerancia bidireccional de 4px para compensar el movimiento entre frames
        // (cuando la plataforma baja, los pies quedan por encima del top momentáneamente)
        constexpr float TOLERANCE = 4.0F;
        if (player_feet >= platform_top - TOLERANCE && player_feet <= platform_top + TOLERANCE) {
            return platform.get();
        }
    }

    return nullptr;
}
