import { LocationEntityModel } from "../features/campaign-entities/models/LocationEntityModel.js";
import { CampaignEntityVisibilityManager } from "../features/campaign-entities/services/CampaignEntityVisibilityManager.js";
import { CampaignEntityDisclosureManager } from "../features/campaign-entities/services/CampaignEntityDisclosureManager.js";
import { LocationEntityStore } from "../features/campaign-entities/services/LocationEntityStore.js";
import { LocationGeneratorRegistry } from "../features/campaign-entities/services/LocationGeneratorRegistry.js";
import { LocationCreationGateway } from "../features/campaign-entities/services/LocationCreationGateway.js";
import { LocationActionRegistry } from "../features/campaign-entities/services/LocationActionRegistry.js";
import { LocationViewRegistry } from "../features/campaign-entities/services/LocationViewRegistry.js";
import { LocationEditorSectionRegistry } from "../features/campaign-entities/services/LocationEditorSectionRegistry.js";
import { LocationSceneService } from "../features/campaign-entities/services/LocationSceneService.js";
import { SiteCoverCatalog } from "../features/site/services/SiteCoverCatalog.js";
import { LocationOverviewViewModel } from "../features/campaign-entities/models/LocationOverviewViewModel.js";
import { SettlementDossierProviderRegistry } from "../features/campaign-entities/services/SettlementDossierProviderRegistry.js";
import { LOCATION_DOSSIER_VIEW_IDS as CORE_LOCATION_DOSSIER_VIEW_IDS } from "../features/campaign-entities/services/LocationDossierViewIds.js";
export const LOCATION_DOSSIER_VIEW_IDS = CORE_LOCATION_DOSSIER_VIEW_IDS;
export const createLocation = data => LocationEntityStore.createLocation(data);
export const getLocation = id => LocationEntityStore.getLocation(id);
export const getLocations = filters => LocationEntityStore.getLocations(filters);
export function getChildLocations(parentLocationId) {
    const parentId = String(parentLocationId || "").trim();
    if (!parentId) return [];
    const parent = getLocation(parentId);
    if (parent && !CampaignEntityDisclosureManager.canUserViewDetails(parent, game.user)) return [];
    return getLocations()
        .filter(entity => entity.hierarchy?.parent?.kind === "location" && entity.hierarchy.parent.locationId === parentId)
        .filter(entity => CampaignEntityVisibilityManager.canUserSee(entity));
}
export function getResolvedLocationCover(idOrEntity) {
    const entity = typeof idOrEntity === "string" ? getLocation(idOrEntity) : idOrEntity;
    if (!entity || !CampaignEntityDisclosureManager.canUserViewDetails(entity, game.user)) return "";
    return LocationEntityModel.getCoverImage(entity)
        || SiteCoverCatalog.getAbstractCover(entity.id || LocationEntityModel.getName(entity) || "location");
}
export const updateLocation = (id, patch, options) => LocationEntityStore.updateLocation(id, patch, options);
export async function deleteLocation(id) {
    const { PlaceDeletionManager } = await import("../features/places/services/PlaceDeletionManager.js");
    return PlaceDeletionManager.deleteLocationBranch(id);
}
export const getLocationScene = id => {
    const entity = getLocation(id);
    return entity && CampaignEntityDisclosureManager.canUserViewDetails(entity, game.user)
        ? LocationSceneService.getPrimaryScene(entity.id)
        : null;
};
export const createLocationScene = id => LocationSceneService.create(id);
export const linkLocationScene = (id, sceneId) => LocationSceneService.link(id, sceneId);
export const replaceLocationScene = (id, sceneId) => LocationSceneService.replace(id, sceneId);
export const detachLocationScene = id => LocationSceneService.detach(id);
export const openLocationScene = id => {
    const entity = getLocation(id);
    return entity
        && CampaignEntityVisibilityManager.canUserSee(entity, game.user)
        && CampaignEntityDisclosureManager.canUserViewDetails(entity, game.user)
        ? LocationSceneService.open(entity.id)
        : null;
};
async function openPlayerSafeLocation(entity, openFullView) {
    if (!entity) return null;
    if (!CampaignEntityVisibilityManager.canUserSee(entity, game.user)) {
        ui.notifications.warn("That location is not currently visible.");
        return null;
    }
    if (!CampaignEntityDisclosureManager.canUserViewDetails(entity, game.user)) {
        const { LocationLimitedPreview } = await import("../features/campaign-entities/applications/LocationLimitedPreview.js");
        return LocationLimitedPreview.show({ locationId: entity.id });
    }
    return openFullView();
}
export async function openLocationDossier(id) { const entity = getLocation(id); return openPlayerSafeLocation(entity, async () => { const { LocationDossier } = await import("../features/campaign-entities/applications/LocationDossier.js"); return LocationDossier.show({ locationId: entity.id }); }); }
export async function openSettlementDossier(idOrEntity) { const entity = typeof idOrEntity === "string" ? getLocation(idOrEntity) : idOrEntity; return openPlayerSafeLocation(entity, async () => { const { SettlementDossier } = await import("../features/campaign-entities/applications/SettlementDossier.js"); return SettlementDossier.show({ locationId: entity.id }); }); }
export async function openLocation(idOrEntity) { const entity = typeof idOrEntity === "string" ? getLocation(idOrEntity) : idOrEntity; return openPlayerSafeLocation(entity, () => { const primaryView = LocationViewRegistry.getPrimaryFor(entity); return primaryView ? LocationViewRegistry.open(primaryView.id, entity) : openLocationDossier(entity.id); }); }
export async function createLocationDossierPanel(options = {}) { const { LocationDossierPanelController } = await import("../features/campaign-entities/services/LocationDossierPanelController.js"); return new LocationDossierPanelController(options); }
export function getLocationConnectionTarget(idOrEntity) { const entity = typeof idOrEntity === "string" ? getLocation(idOrEntity) : idOrEntity; return entity && CampaignEntityDisclosureManager.canUserViewDetails(entity, game.user) ? { id: `nexus-entity:${entity.id}`, kind: "nexus-entity", entityId: entity.id, entityType: "location", uuid: entity.uuid || "", name: LocationEntityModel.getName(entity), img: LocationEntityModel.getThumbnail(entity), category: "place", subtitle: LocationEntityModel.getSubtitle(entity) } : null; }
export function getLocationOverview(idOrEntity) { const entity = typeof idOrEntity === "string" ? getLocation(idOrEntity) : idOrEntity; return entity && CampaignEntityDisclosureManager.canUserViewDetails(entity, game.user) ? LocationOverviewViewModel.fromEntity(entity) : null; }
export const registerLocationGenerator = definition => LocationGeneratorRegistry.register(definition);
export const openLocationCreator = options => LocationCreationGateway.open(options);
export const registerLocationAction = definition => LocationActionRegistry.register(definition);
export const registerLocationEditorSection = definition => LocationEditorSectionRegistry.register(definition);
export const getLocationGenerators = () => LocationGeneratorRegistry.list();
export const getLocationGeneratorOptions = id => LocationGeneratorRegistry.getOptions(id);
export const getLocationGeneratorProfileOptions = (id, context) => LocationGeneratorRegistry.getProfileOptions(id, context);
export function canRerollLocationCurrentThread(idOrEntity) {
    const entity = typeof idOrEntity === "string" ? getLocation(idOrEntity) : idOrEntity;
    return !!entity && LocationGeneratorRegistry.canRerollCurrentThread(entity.generation?.generatorId);
}
export async function rerollLocationCurrentThread(idOrEntity, options = {}) {
    if (!game.user?.isGM) return null;
    const entity = typeof idOrEntity === "string" ? getLocation(idOrEntity) : idOrEntity;
    if (!entity) return null;
    const generatorId = String(entity.generation?.generatorId || "").trim();
    if (!LocationGeneratorRegistry.canRerollCurrentThread(generatorId)) return null;
    const result = await LocationGeneratorRegistry.rerollCurrentThread(generatorId, {
        entity,
        seed: String(options.seed || "")
    });
    if (!result || typeof result !== "object" || Array.isArray(result)) return null;
    const currentThread = {};
    for (const key of ["state", "pressure", "opportunity", "secret"]) {
        if (Object.hasOwn(result, key)) currentThread[key] = String(result[key] || "").trim();
    }
    return Object.keys(currentThread).length ? updateLocation(entity.id, { currentThread }) : null;
}
export const composeLocationGeneratorCandidate = (id, candidate, options) => LocationGeneratorRegistry.composeCandidate(id, candidate, options);
export const reconcileLocationGeneratorCandidate = (id, candidate, composition) => LocationGeneratorRegistry.reconcileCandidate(id, candidate, composition);
export const renderLocationGeneratorCandidatePreview = (id, candidate, composition) => LocationGeneratorRegistry.renderCandidatePreview(id, candidate, composition);
export const generateLocation = (id, options) => LocationGeneratorRegistry.generate(id, options);
export const registerLocationView = definition => LocationViewRegistry.register(definition);
export const registerSettlementDossierProvider = definition => SettlementDossierProviderRegistry.register(definition);
export function getLocationViews(idOrEntity) { const entity = typeof idOrEntity === "string" ? getLocation(idOrEntity) : idOrEntity; return entity && CampaignEntityDisclosureManager.canUserViewDetails(entity, game.user) ? LocationViewRegistry.listFor(entity) : []; }
export function openLocationView(viewId, idOrEntity) { const entity = typeof idOrEntity === "string" ? getLocation(idOrEntity) : idOrEntity; return openPlayerSafeLocation(entity, () => LocationViewRegistry.open(viewId, entity)); }
export function getLocationPlayerDisclosure(idOrEntity) { const entity = typeof idOrEntity === "string" ? getLocation(idOrEntity) : idOrEntity; return entity ? CampaignEntityDisclosureManager.getEffectivePlayerDisclosure(entity) : null; }
export function getLocationPlayerDisclosureOverride(idOrEntity) { const entity = typeof idOrEntity === "string" ? getLocation(idOrEntity) : idOrEntity; return entity ? CampaignEntityDisclosureManager.getPlayerDisclosureOverride(entity) : null; }
export function setLocationPlayerDisclosure(idOrUuid, value) { return CampaignEntityDisclosureManager.setPlayerDisclosureOverride(idOrUuid, "location", value); }
export function canUserViewLocationDetails(idOrEntity, user = game.user) { const entity = typeof idOrEntity === "string" ? getLocation(idOrEntity) : idOrEntity; return !!entity && CampaignEntityVisibilityManager.canUserSee(entity, user) && CampaignEntityDisclosureManager.canUserViewDetails(entity, user); }
