#include "StandbyExecutor.h"

#include <optional>

#include <QVector2D>

#include "BehaviorKind.h"
#include "Centroid.h"
#include "EntityAdmin.h"
#include "FactionComponent.h"
#include "HealthComponent.h"
#include "MovementIntentComponent.h"
#include "PositionComponent.h"
#include "SelectedBehaviorComponent.h"
#include "ShipIdentityComponent.h"
#include "StandbyBehavior.h"
#include "StationBodyComponent.h"
#include "tracing.h"

void StandbyExecutor::execute(EntityAdmin& admin)
{
    TRACE();

    // Centroid of each faction's alive ships; a standing-by ship steers toward the
    // center of its other same-faction ships so it stays among potential patients.
    Centroid enemyShips;
    Centroid playerShips;
    admin.forEach<ShipIdentityComponent, PositionComponent, FactionComponent, HealthComponent>(
        [&enemyShips, &playerShips](entt::entity /*e*/, const ShipIdentityComponent& /*si*/,
            const PositionComponent& pos, const FactionComponent& faction,
            const HealthComponent& health)
        {
            if (health.hp <= 0.0f) { return; }
            Centroid& centroid = faction.isEnemy ? enemyShips : playerShips;
            centroid.add(pos.value);
        });

    // Fallback per faction: the centroid of that side's own alive defence stations.
    Centroid enemyStations;
    Centroid playerStations;
    admin.forEach<StationBodyComponent, PositionComponent, FactionComponent, HealthComponent>(
        [&enemyStations, &playerStations](entt::entity /*e*/,
            const StationBodyComponent& /*sb*/, const PositionComponent& pos,
            const FactionComponent& faction, const HealthComponent& health)
        {
            if (health.hp <= 0.0f) { return; }
            Centroid& centroid = faction.isEnemy ? enemyStations : playerStations;
            centroid.add(pos.value);
        });

    const std::optional<QVector2D> enemyStationCenter  = enemyStations.value();
    const std::optional<QVector2D> playerStationCenter = playerStations.value();

    admin.forEach<StandbyBehavior, SelectedBehaviorComponent, PositionComponent,
                  FactionComponent, MovementIntentComponent>(
        [&](entt::entity /*e*/, const StandbyBehavior& /*standby*/,
            const SelectedBehaviorComponent& selected, const PositionComponent& pos,
            const FactionComponent& faction, MovementIntentComponent& intent)
        {
            if (selected.winner != BehaviorKind::Standby) { return; }

            const Centroid& allyShips = faction.isEnemy ? enemyShips : playerShips;
            const std::optional<QVector2D>& friendlyStationCenter =
                faction.isEnemy ? enemyStationCenter : playerStationCenter;

            // Aim at the centroid of the other allied ships (excluding self), then
            // fall back to the friendly stations, then hold position when alone.
            QVector2D target = pos.value;
            if (allyShips.count > 1)
            {
                target = (allyShips.sum - pos.value)
                    / static_cast<float>(allyShips.count - 1);
            }
            else if (friendlyStationCenter)
            {
                target = *friendlyStationCenter;
            }
            intent = MovementIntentComponent{true, target};
        });
}
