/* eslint-disable @typescript-eslint/ban-ts-comment */
// @ts-nocheck

import { rebuildChunkEntrySurface } from "./pixiChunkSurfaceHelpers";

function buildChunkSurfaceOptions(state, scope, helpers) {
  return {
    baseTileSize: scope.baseTileSize,
    chunkSize: state.chunkSize,
    getTileOpacity: helpers.getTileOpacity,
    getTileSurface: helpers.getTileSurface,
    syncChunkEntryDimensions: helpers.syncChunkEntryDimensions,
    tileSize: scope.tileSize,
  };
}

export function rebuildSceneFromWorldChunks(state, scope, helpers) {
  const worldContext = helpers.getWorldChunkRenderContext();
  if (!worldContext) {
    return false;
  }
  helpers.resetSceneRoots();
  const chunkSurfaceOptions = buildChunkSurfaceOptions(state, scope, helpers);
  const desiredKeys = new Set();
  const activeLayerNumbers = new Set();
  worldContext.chunks.forEach((chunk) => {
    const chunkX = Math.floor(Number(chunk?.chunkX) || 0);
    const chunkY = Math.floor(Number(chunk?.chunkY) || 0);
    const tileX = (chunkX - worldContext.originChunkX) * worldContext.chunkWidth;
    const tileY = (chunkY - worldContext.originChunkY) * worldContext.chunkHeight;
    const roomLayers = Array.isArray(chunk?.roomLayers) ? chunk.roomLayers : [];
    roomLayers.forEach((layerObj) => {
      const layerNumber = Number(layerObj?.layer) || 0;
      activeLayerNumbers.add(layerNumber);
      const layerRoot = helpers.getOrCreateLayerRoot(layerNumber);
      layerRoot.visible = scope.isLayerRendered(layerNumber);
      const chunkKey = helpers.buildLayerChunkKey(layerNumber, chunkX, chunkY);
      desiredKeys.add(chunkKey);
      let entry = state.chunkEntries.get(chunkKey) || null;
      if (!entry) {
        entry = helpers.createChunkEntry(layerNumber, chunkX, chunkY, {
          tileX,
          tileY,
          tileWidth: worldContext.chunkWidth,
          tileHeight: worldContext.chunkHeight,
        });
      }
      if (entry.tileX !== tileX || entry.tileY !== tileY) {
        entry.tileX = tileX;
        entry.tileY = tileY;
        entry.sprite.x = tileX;
        entry.sprite.y = tileY;
      }
      if (entry.tileWidth !== worldContext.chunkWidth || entry.tileHeight !== worldContext.chunkHeight) {
        entry.tileWidth = worldContext.chunkWidth;
        entry.tileHeight = worldContext.chunkHeight;
      }
      const hasContent = rebuildChunkEntrySurface(
        entry,
        (localX, localY) => helpers.resolveWorldChunkLayerSymbol(chunk, layerObj, localX, localY),
        worldContext.chunkWidth,
        worldContext.chunkHeight,
        String(chunk?.backgroundTileId || ""),
        chunkSurfaceOptions,
      );
      if (!hasContent && layerNumber > 0) {
        helpers.destroyChunkEntry(entry);
        desiredKeys.delete(chunkKey);
      }
    });
  });
  Array.from(state.chunkEntries.entries()).forEach(([key, entry]) => {
    if (!desiredKeys.has(key)) {
      helpers.destroyChunkEntry(entry);
    }
  });
  Array.from(state.layerRoots.entries()).forEach(([layerNumber, layerRoot]) => {
    if (!activeLayerNumbers.has(layerNumber)) {
      state.npcSpritesById.forEach((sprite, npcId) => {
        if (sprite?.parent && sprite.parent === state.entityLayerRoots.get(layerNumber)) {
          state.npcSpritesById.delete(npcId);
        }
      });
      state.entityLayerRoots.delete(layerNumber);
      layerRoot.removeFromParent();
      layerRoot.destroy({ children: true });
      state.layerRoots.delete(layerNumber);
    }
  });
  return true;
}

export function rebuildSceneFromRoomLayers(state, scope, helpers) {
  state.chunkEntries.forEach((entry) => {
    helpers.destroyChunkEntry(entry);
  });
  state.chunkEntries.clear();
  state.layerRoots.forEach((layerRoot) => {
    layerRoot.removeFromParent();
    layerRoot.destroy({ children: true });
  });
  state.layerRoots.clear();
  state.entityLayerRoots.clear();
  state.npcSpritesById.clear();

  helpers.resetSceneRoots();

  const chunkSurfaceOptions = buildChunkSurfaceOptions(state, scope, helpers);
  const layers = Array.isArray(scope.roomLayers)
    ? [...scope.roomLayers].sort((a, b) => (Number(a.layer) || 0) - (Number(b.layer) || 0))
    : [];
  layers.forEach((layerObj) => {
    const layerNumber = Number(layerObj?.layer) || 0;
    const layerRoot = helpers.getOrCreateLayerRoot(layerNumber);
    layerRoot.visible = scope.isLayerRendered(layerNumber);
    const chunkStartsX = Math.ceil(Math.max(1, Number(scope.width) || 1) / state.chunkSize);
    const chunkStartsY = Math.ceil(Math.max(1, Number(scope.height) || 1) / state.chunkSize);
    for (let chunkY = 0; chunkY < chunkStartsY; chunkY += 1) {
      for (let chunkX = 0; chunkX < chunkStartsX; chunkX += 1) {
        const baseTileX = chunkX * state.chunkSize;
        const baseTileY = chunkY * state.chunkSize;
        const tileWidth = Math.max(1, Math.min(state.chunkSize, Math.max(0, Number(scope.width) || 0) - baseTileX));
        const tileHeight = Math.max(1, Math.min(state.chunkSize, Math.max(0, Number(scope.height) || 0) - baseTileY));
        const chunkEntry = helpers.getOrCreateChunkEntry(layerNumber, chunkX, chunkY, {
          tileX: baseTileX,
          tileY: baseTileY,
          tileWidth,
          tileHeight,
        });
        const hasContent = rebuildChunkEntrySurface(
          chunkEntry,
          (localX, localY) => helpers.resolveStoredTileSymbol(layerObj, baseTileX + localX, baseTileY + localY),
          tileWidth,
          tileHeight,
          String(layerNumber),
          chunkSurfaceOptions,
        );
        if (!hasContent) {
          helpers.destroyChunkEntry(chunkEntry);
        }
      }
    }
  });
  return true;
}
