//
// Created by sebastian on 04.08.26.
//

#include "HighlightSystem.h"


#include "ecs/standardComponents/HighlightComponent.h"
#include "ecs/systems/PickingSystem.h"

void ludo::HighlightSystem::update(const engine::Mouse& mouse, engine::EntityRegistry &registry) {
    auto [origin, dir] = engine::PickingSystem::screenToRay(mouse.getXY(/*ndc=*/true), m_camera);
    float closestT = std::numeric_limits<float>::max();
    std::optional<engine::Entity> hit;

    for (const auto& entity : m_highlightedEntities) {
        registry.removeComponent<engine::HighlightComponent>(entity);
    }
    m_highlightedEntities.clear();

    for (const auto& [entity, pickable] : registry.getPool<engine::PickableComponent>()) {
        const auto transform = registry.getComponent<engine::TransformComponent>(entity);
        const auto mesh = registry.getComponent<engine::MeshComponent>(entity);

        engine::AABB transformedAABB = mesh.model->getAABB().transformed(transform.computeModelMatrix());
        engine::Ray ray = engine::Ray(origin, dir);
        std::optional<engine::RayHit> ray_hit = transformedAABB.intersects(engine::Ray(origin, dir), closestT);
        if (transformedAABB.intersects(ray, closestT).has_value()) {
            closestT = ray_hit.value().distance;
            hit = entity;
        }
    }

    if (hit.has_value()) {
        registry.addComponent<engine::HighlightComponent>(hit.value(), engine::HighlightComponent({1.0, 1.0f, 1.0}, 0.4f));
        m_highlightedEntities.push_back(hit.value());
    }
}
