using System;
using System.Collections.Generic;
namespace AcDream.App.Rendering.Wb;
///
/// Phase A8 (2026-05-26): per-landblock registry of s.
/// Two-way indexed for O(1) cell→building and building-id→building lookups.
/// Built once per landblock at load time by ;
/// no mutations occur after initial population.
///
/// The cell→building index uses a List<Building> value type
/// to handle the (rare but valid) case where two buildings share an EnvCell —
/// each building performs its own BFS so a shared boundary cell ends up in both
/// EnvCellIds sets. returns all
/// owners so RR7's render path can pick the correct one.
///
/// WB reference: WorldBuilder.Shared/Services/PortalService.cs
/// (BuildingPortalGroup). Design:
/// docs/superpowers/specs/2026-05-26-phase-a8-wb-full-port-design.md.
///
public sealed class BuildingRegistry
{
// Index 1: cell-id → list of buildings containing that cell.
// Cells may belong to multiple buildings (rare; handled via List).
private readonly Dictionary> _byCellId = new();
// Index 2: building-id → Building.
private readonly Dictionary _byBuildingId = new();
///
/// Adds a building to both indexes. Idempotent if the exact same
/// instance is added twice with the same
/// .
///
/// The building to register.
public void Add(Building b)
{
if (_byBuildingId.TryGetValue(b.BuildingId, out var existing) && ReferenceEquals(existing, b))
return;
_byBuildingId[b.BuildingId] = b;
foreach (var cellId in b.EnvCellIds)
{
if (!_byCellId.TryGetValue(cellId, out var list))
{
list = new List();
_byCellId[cellId] = list;
}
if (!list.Contains(b)) list.Add(b);
}
}
///
/// Returns the buildings containing .
/// Returns an empty read-only list when the cell isn't part of any
/// building (outdoor cells, dungeon cells not tagged by
/// LandBlockInfo.Buildings).
///
/// Full 32-bit cell id.
public IReadOnlyList GetBuildingsContainingCell(uint cellId) =>
_byCellId.TryGetValue(cellId, out var list) ? list : Array.Empty();
/// Returns the building with the given id, or null if not found.
/// The building id as allocated by .
public Building? GetById(uint buildingId) =>
_byBuildingId.TryGetValue(buildingId, out var b) ? b : null;
/// Enumerates every registered building in unspecified order.
public IEnumerable All() => _byBuildingId.Values;
/// Number of registered buildings.
public int Count => _byBuildingId.Count;
}