#pragma once

#include <optional>
#include <string>

#include <QPoint>

#include "BuildingId.h"
#include "BuildingType.h"
#include "ShipLayout.h"

struct Building;
struct ConstructionSite;
struct SelectionContext;

// One selected building id resolved to whichever of the two things it names: an
// operational building or a construction site still queued or under construction. A
// site carries the same configuration as the building it will become
// (REQ-BLD-SITE-CONFIG), so the fields both have are read out here once instead of in
// every content that shows a single building.
struct BuildingTarget
{
    const Building*         building = nullptr;  // null while it is still a site
    const ConstructionSite* site     = nullptr;  // null once it is built

    BuildingType type = BuildingType::Miner;
    std::string  recipeId;
    std::optional<ShipLayoutConfig> shipLayout;
    QPoint       anchor;

    // False when the id names neither -- the object went away under the panel (it was
    // deconstructed, or its site finished and its id was reused).
    bool isValid() const { return building != nullptr || site != nullptr; }
};

// Resolves the id against the current factory state. The returned pointers are only
// valid until the simulation next mutates, so this is called per refresh rather than
// cached.
BuildingTarget resolveBuildingTarget(const SelectionContext& context, BuildingId id);

// The id wrapped as a construction site id when it names one, nullopt when it names an
// operational building. Every content showing a single building hands this to
// SelectionContent so the base can apply the site rule (REQ-UI-SELECTION-CARD).
std::optional<BuildingId> asConstructionSite(const SelectionContext& context,
                                            BuildingId id);
