import { Rectangle } from "../../../pixi/pixi.mjs";
import { BC_CHUNKS_SETTINGS, BC_TERRAIN_SETTINGS } from "../../GlobalVariables/GlobalVariables";
import { SceneObject } from "../../SceneObjects/SceneObject";
import { Point2D, PointInt2D } from "../../Utils/Math.utils";
import { NavigationGridTile } from "../../World/NavigationGrid/NavigationGrid";
import { CHUNK_LAYER_TERRAIN, Chunk } from "../Chunk/Chunk";
import { TerrainTile } from "../Tiles/TerrainTile";
import { Tile } from "../Tiles/Tile";
import { TerrainGenerator } from "./Generator/TerrainGenerator";
import { createTerrainTileFromTileValue } from "./TerrainTilesFactory/TerrainTilesFactory";

export class Terrain extends SceneObject {
    /**
     * @type {Map<String, Chunk>}
     */
    chunkStorage = new Map();
    /**
     * @type {Map<String, Chunk>}
     */
    visibleChunks = new Map();

    terrainGenerator = new TerrainGenerator();

    /**
     * adds chunk to terrain. Chunk object must contain pivot coordinates
     * @param {Chunk} chunk
     */
    addChunk(chunk) {
        this.chunkStorage.set(chunk.chunkPivotCoordinates.getX() + "_" + chunk.chunkPivotCoordinates.getY(), chunk);
    }

    /**
     * fills chunk with tiles
     * @param {Chunk} chunk
     */
    fillChunk(chunk) {
        let ii = 0;
        let jj = 0;
        for (let i = BC_CHUNKS_SETTINGS.width * chunk.chunkPivotCoordinates.getX(); i < BC_CHUNKS_SETTINGS.width * (chunk.chunkPivotCoordinates.getX() + 1); i++) {
            for (let j = BC_CHUNKS_SETTINGS.height * chunk.chunkPivotCoordinates.getY(); j < BC_CHUNKS_SETTINGS.height * (chunk.chunkPivotCoordinates.getY() + 1); j++) {
                let result = this.terrainGenerator.getValueAt(new Point2D(i, j));
                let resultTile = createTerrainTileFromTileValue(result, new PointInt2D(i * BC_TERRAIN_SETTINGS.totalSize - BC_TERRAIN_SETTINGS.totalSize / 2, j * BC_TERRAIN_SETTINGS.totalSize - BC_TERRAIN_SETTINGS.totalSize / 2));
                resultTile.tileKey = resultTile.worldPosition.getX() + BC_TERRAIN_SETTINGS.totalSize / 2 + "_" + (resultTile.worldPosition.getY() + BC_TERRAIN_SETTINGS.totalSize / 2);
                this.addChild(resultTile);
                resultTile.drawObject.scale.set(BC_TERRAIN_SETTINGS.scale, BC_TERRAIN_SETTINGS.scale);
                resultTile.drawObject.position.set(resultTile.worldPosition.getX(), resultTile.worldPosition.getY());
                resultTile.drawObject.zIndex = resultTile.zOrder;
                chunk.addToLayer(CHUNK_LAYER_TERRAIN, resultTile);
                chunk.navigationChunk.addToChunk(new NavigationGridTile(
                    new PointInt2D(i * BC_TERRAIN_SETTINGS.totalSize, j * BC_TERRAIN_SETTINGS.totalSize),
                    resultTile.navigationCost,
                    resultTile.isObstacle,
                    resultTile
                ), resultTile.tileKey);
                jj++;
            }
            ii++;
        }
        chunk.filled = true;
    }

    /**
     *
     * @param {PointInt2D} point in world coordinates
     * @param {Number} layerId chunk layer id
     * @returns {Tile | undefined}
     */
    getTileAt(point, layerId) {
        let tileKey = Math.floor(point.getX() / BC_TERRAIN_SETTINGS.totalSize) * BC_TERRAIN_SETTINGS.totalSize + "_" + Math.floor(point.getY() / BC_TERRAIN_SETTINGS.totalSize) * BC_TERRAIN_SETTINGS.totalSize;
        let chunkKey = Math.floor(point.getX() / (BC_TERRAIN_SETTINGS.totalSize * BC_CHUNKS_SETTINGS.width)) + "_" + Math.floor(point.getY() / (BC_TERRAIN_SETTINGS.totalSize * BC_CHUNKS_SETTINGS.height));
        let chunk = this.chunkStorage.get(chunkKey);
        if (chunk) {
            switch (layerId) {
                case CHUNK_LAYER_TERRAIN:
                    return chunk.terrainLayer.get(tileKey);
                default:
                    break;
            }
        }
        return undefined;
    }
}
