// @ts-nocheck

import { createHistoryController } from "./historyController";
import { createInteractionController } from "./interactionController";
import { createImportController } from "./importController";
import { createNpcController } from "./npcController";
import { createChangelogSplashWindowController } from "./changelogSplashWindowController";
import { createEntityEditorWindowController } from "./entityEditorWindowController";
import { createEngineOverrideWindowController } from "./engineOverrideWindowController";
import { createPersistenceController } from "./persistenceController";
import { createRenderController } from "./renderController";
import { createSidebarController } from "./sidebarController";
import { createStatusLogWindowController } from "./statusLogWindowController";
import { createTileArtEditorWindowController } from "./tileArtEditorWindowController";
import { createToolWindowController } from "./toolWindowController";
import { createWorldOverviewWindowController } from "./worldOverviewWindowController";
import { createDebouncedCallback } from "./debounce";

export function initializeRuntimeControllers(config) {
  const {
    scope,
    uiScope,
    resetWorkspaceLayout,
    setStatus,
    createNewTile,
    createNewSpriteGraphic,
    duplicateGraphicRecord,
    openTilePaletteContextMenu,
    openPlacedEntityContextMenu,
    applyNpcEditorChange,
    getEditorEngineOverrides,
    saveEditorEngineOverrides,
    getEffectiveHeightBlurStep,
    isRendererDebugEnabled,
    reloadGraphicsContentFromApi,
    syncDocumentTitle,
    syncCanvasDimensionsToTileSize,
    refreshEditorEngineOverridesUi,
    cacheStandaloneMapBootstrap,
    currentMapId,
    persistPopupBounds,
    popupSessionStore,
    windowRef,
    isWorldModeActive,
    getInitialWorldViewTile,
    centerViewportOnWorldTile,
    prefetchAdjacentWorldNeighborhoods,
    worldRuntimeState,
    syncWorldNeighborhoodForViewport,
    drawNow,
    setControllerRefs,
  } = config;

  const toolWindowController = createToolWindowController(scope);
  const tileArtEditorWindowController = createTileArtEditorWindowController(scope);
  const entityEditorWindowController = createEntityEditorWindowController(scope);
  const engineOverrideWindowController = createEngineOverrideWindowController(scope);
  const worldOverviewWindowController = createWorldOverviewWindowController(scope);
  const changelogSplashWindowController = createChangelogSplashWindowController(scope);
  const statusLogWindowController = createStatusLogWindowController(scope);

  const syncToolPanels = () => toolWindowController.syncPanels();
  const handleSidebarTabButtonClick = (tab) => toolWindowController.handleTabButtonClick(tab);
  const restoreAllToolWindows = () => toolWindowController.restoreAllWindows();
  const openTileArtEditorWindow = (recordTypeOrId, maybeRecordId) => tileArtEditorWindowController.open(recordTypeOrId, maybeRecordId);
  const closeTileArtEditorWindow = () => tileArtEditorWindowController.close();
  const openEntityEditorWindow = (entityId) => entityEditorWindowController.open(entityId);
  const closeEntityEditorWindow = () => entityEditorWindowController.close();
  const openEngineOverrideWindow = () => engineOverrideWindowController.open();
  const closeEngineOverrideWindow = () => engineOverrideWindowController.close();
  const refreshEngineOverrideWindow = () => engineOverrideWindowController.refresh();
  const refreshEngineOverrideSummary = () => engineOverrideWindowController.updateSummary();
  const openWorldOverviewWindow = () => worldOverviewWindowController.open();
  const closeWorldOverviewWindow = () => worldOverviewWindowController.close();
  const refreshWorldOverviewWindow = () => worldOverviewWindowController.refresh();
  const invalidateWorldOverviewChunkSurfaces = (chunkKeys, options) => worldOverviewWindowController.invalidateChunkSurfaces?.(chunkKeys, options);
  const openStatusLogWindow = () => statusLogWindowController.open();
  const closeStatusLogWindow = () => statusLogWindowController.close();
  const openNewsWindow = (options = {}) => changelogSplashWindowController.open({ markSeen: false, ...options });
  const resetWorkspaceLayoutFlow = () => {
    resetWorkspaceLayout();
    toolWindowController.restoreAllWindows();
    setStatus("Workspace layout reset.", false);
  };

  scope.syncToolPanels = syncToolPanels;
  scope.handleSidebarTabButtonClick = handleSidebarTabButtonClick;
  scope.restoreAllToolWindows = restoreAllToolWindows;
  scope.resetWorkspaceLayout = resetWorkspaceLayoutFlow;
  scope.createNewTile = createNewTile;
  scope.createNewSpriteGraphic = createNewSpriteGraphic;
  scope.duplicateGraphicRecord = duplicateGraphicRecord;
  scope.openTileArtEditorWindow = openTileArtEditorWindow;
  scope.closeTileArtEditorWindow = closeTileArtEditorWindow;
  scope.openEntityEditorWindow = openEntityEditorWindow;
  scope.closeEntityEditorWindow = closeEntityEditorWindow;
  scope.openEngineOverrideWindow = openEngineOverrideWindow;
  scope.closeEngineOverrideWindow = closeEngineOverrideWindow;
  scope.refreshEngineOverrideWindow = refreshEngineOverrideWindow;
  scope.refreshEngineOverrideSummary = refreshEngineOverrideSummary;
  scope.openWorldOverviewWindow = openWorldOverviewWindow;
  scope.closeWorldOverviewWindow = closeWorldOverviewWindow;
  scope.refreshWorldOverviewWindow = refreshWorldOverviewWindow;
  scope.invalidateWorldOverviewChunkSurfaces = invalidateWorldOverviewChunkSurfaces;
  scope.openStatusLogWindow = openStatusLogWindow;
  scope.closeStatusLogWindow = closeStatusLogWindow;
  scope.openNewsWindow = openNewsWindow;
  scope.openTilePaletteContextMenu = openTilePaletteContextMenu;
  scope.openPlacedEntityContextMenu = openPlacedEntityContextMenu;
  scope.applyNpcEditorChange = applyNpcEditorChange;
  scope.getEditorEngineOverrides = getEditorEngineOverrides;
  scope.saveEditorEngineOverrides = saveEditorEngineOverrides;
  scope.getEffectiveHeightBlurStep = getEffectiveHeightBlurStep;
  scope.isRendererDebugEnabled = isRendererDebugEnabled;
  scope.reloadGraphicsContentFromApi = reloadGraphicsContentFromApi;

  uiScope.syncToolPanels = syncToolPanels;
  uiScope.handleSidebarTabButtonClick = handleSidebarTabButtonClick;
  uiScope.restoreAllToolWindows = restoreAllToolWindows;
  uiScope.resetWorkspaceLayout = resetWorkspaceLayoutFlow;
  uiScope.createNewTile = createNewTile;
  uiScope.createNewSpriteGraphic = createNewSpriteGraphic;
  uiScope.duplicateGraphicRecord = duplicateGraphicRecord;
  uiScope.openEntityEditorWindow = openEntityEditorWindow;
  uiScope.closeEntityEditorWindow = closeEntityEditorWindow;
  uiScope.openEngineOverrideWindow = openEngineOverrideWindow;
  uiScope.closeEngineOverrideWindow = closeEngineOverrideWindow;
  uiScope.refreshEngineOverrideWindow = refreshEngineOverrideWindow;
  uiScope.refreshEngineOverrideSummary = refreshEngineOverrideSummary;
  uiScope.openWorldOverviewWindow = openWorldOverviewWindow;
  uiScope.closeWorldOverviewWindow = closeWorldOverviewWindow;
  uiScope.refreshWorldOverviewWindow = refreshWorldOverviewWindow;
  uiScope.invalidateWorldOverviewChunkSurfaces = invalidateWorldOverviewChunkSurfaces;
  uiScope.openStatusLogWindow = openStatusLogWindow;
  uiScope.closeStatusLogWindow = closeStatusLogWindow;
  uiScope.openNewsWindow = openNewsWindow;
  uiScope.openTilePaletteContextMenu = openTilePaletteContextMenu;
  uiScope.openPlacedEntityContextMenu = openPlacedEntityContextMenu;
  uiScope.applyNpcEditorChange = applyNpcEditorChange;
  uiScope.getEditorEngineOverrides = getEditorEngineOverrides;
  uiScope.saveEditorEngineOverrides = saveEditorEngineOverrides;
  uiScope.getEffectiveHeightBlurStep = getEffectiveHeightBlurStep;
  uiScope.isRendererDebugEnabled = isRendererDebugEnabled;
  uiScope.reloadGraphicsContentFromApi = reloadGraphicsContentFromApi;

  syncDocumentTitle();
  const historyController = createHistoryController(scope);
  const npcController = createNpcController(scope);
  const sidebarController = createSidebarController(scope);
  const renderController = createRenderController(scope);
  const persistenceController = createPersistenceController(scope);
  const importController = createImportController(scope);
  const interactionController = createInteractionController(scope);
  const controllerRefs = {
    historyController,
    npcController,
    sidebarController,
    renderController,
    persistenceController,
    importController,
    interactionController,
  };

  if (typeof setControllerRefs === "function") {
    setControllerRefs(controllerRefs);
  }

  const persistPopupBoundsDeferred = createDebouncedCallback(() => {
    persistPopupBounds();
  }, 160);

  syncCanvasDimensionsToTileSize();
  toolWindowController.initialize();
  tileArtEditorWindowController.initialize();
  entityEditorWindowController.initialize();
  engineOverrideWindowController.initialize();
  worldOverviewWindowController.initialize();
  changelogSplashWindowController.initialize();
  statusLogWindowController.initialize();
  renderController.initializeRenderAssets();
  interactionController.initializeEditorState();
  interactionController.bindDomEvents();
  interactionController.initializeUi();
  refreshEditorEngineOverridesUi();
  cacheStandaloneMapBootstrap(currentMapId);

  if (isWorldModeActive()) {
    windowRef.requestAnimationFrame(() => {
      const initialWorldView = getInitialWorldViewTile();
      centerViewportOnWorldTile(initialWorldView.worldTileX, initialWorldView.worldTileY);
      prefetchAdjacentWorldNeighborhoods(worldRuntimeState.centerChunkX, worldRuntimeState.centerChunkY);
      syncWorldNeighborhoodForViewport();
      drawNow();
      setStatus("World mode loaded. Endless navigation is active.", false);
    });
  }

  windowRef.requestAnimationFrame(() => {
    changelogSplashWindowController.maybeOpenForCurrentVersion();
  });
  windowRef.addEventListener("resize", () => {
    persistPopupBoundsDeferred();
  });
  windowRef.addEventListener("beforeunload", () => {
    popupSessionStore.flushPersistedLayout(windowRef);
    persistPopupBounds();
  });

  return {
    ...controllerRefs,
    statusLogWindowController,
    changelogSplashWindowController,
    persistPopupBoundsDeferred,
  };
}
