import {Noise} from "noisejs";
import { Rectangle } from "../../pixi/pixi.mjs";
import { BC_CAMERA, BC_CHUNKS_SETTINGS, BC_CURRENT_SCENE, BC_SPRITES_SETTINGS, BC_TERRAIN_SETTINGS, PRNG } from "../GlobalVariables/GlobalVariables";
import { NumberCue, RGBColor } from "../Utils/DataTypes.utils";
import { ChunkStorageTypes, WorldChunk } from "./WorldChunk/WorldGenChunk";
import { TerrainTile, TerrainTileProps } from "./WorldObjects/TerrainTile/TerrainTile";
import { clampNumber } from "../Utils/Math.utils";
import { addGameObjectToGameState } from "../GameState/GameState";

/**
 * @type Map<String, WorldChunk>
 */
const WorldChunksStorage = new Map();


/* #### REWRITE PART START ####*/
const terrainSpriteList = {
    0: { x: 21, y: 21 }, //water
    1: { x: 2, y: 21 }, //sand
    2: { x: 2, y: 2 }, //grass
    3: { x: 21, y: 2 }, //stone
};
const terrainTypeList = {
    0: "ter_water", //water
    1: "ter_sand", //sand
    2: "ter_grass", //grass
    3: "ter_stone", //stone
};
const grassVegetationSpriteList = {
    0: { x: 10, y: 11 },
    1: { x: 11, y: 11 },
    2: { x: 12, y: 11 },
    3: { x: 13, y: 11 },
    4: { x: 14, y: 11 },
    5: { x: 15, y: 11 },
    6: { x: 16, y: 11 },
    7: { x: 17, y: 11 },
    8: { x: 18, y: 11 },
    9: { x: 19, y: 11 },
    10: { x: 0, y: 12 },
    11: { x: 1, y: 12 },
    12: { x: 2, y: 12 },
    13: { x: 3, y: 12 },
    14: { x: 7, y: 13 },
    15: { x: 7, y: 12 },
    16: { x: 8, y: 12 },
    17: { x: 9, y: 12 },
};
const sandVegetationSpriteList = {
    0: { x: 14, y: 10 },
    1: { x: 7, y: 13 },
    2: { x: 6, y: 13 },
    3: { x: 5, y: 13 },
    4: { x: 4, y: 13 },
    5: { x: 3, y: 13 },
};
const stoneVegetationSpriteList = {
    0: { x: 5, y: 13 },
    1: { x: 4, y: 13 },
    2: { x: 3, y: 13 },
};
const grassVegResourcesList = {
    0: { type: "grass", num: 10 / 5 },
    1: { type: "grass", num: 9 / 5 },
    2: { type: "grass", num: 8 / 5 },
    3: { type: "grass", num: 7 / 5 },
    4: { type: "grass", num: 4 / 5 },
    5: { type: "grass", num: 4 / 5 },
    6: { type: "grass", num: 5 / 5 },
    7: { type: "grass", num: 3 / 5 },
    8: { type: "grass", num: 2 / 5 },
    9: { type: "grass", num: 1 / 5 },
    10: { type: "grass", num: 2 / 5 },
    11: { type: "grass", num: 2 / 5 },
    12: { type: "grass", num: 2 / 5 },
    13: { type: "grass", num: 2 / 5 },
    14: { type: "stone", num: 1 / 5 },
    15: { type: "wood", num: 2 / 5 },
    16: { type: "wood", num: 2 / 5 },
    17: { type: "wood", num: 2 / 5 },
};

const sandVegResourcesList = {
    0: { type: "grass", num: 4 / 5 },
    1: { type: "stone", num: 1 / 5 },
    2: { type: "stone", num: 3 / 5 },
    3: { type: "stone", num: 4 / 5 },
    4: { type: "stone", num: 5 / 5 },
    5: { type: "stone", num: 5 / 5 },
};

const stoneVegResourcesList = {
    0: { type: "stone", num: 4 / 5 },
    1: { type: "stone", num: 5 / 5 },
    2: { type: "stone", num: 5 / 5 },
};

let noise = new Noise(Math.floor(PRNG() * 188822321));
let noiseErosion = new Noise(Math.floor(PRNG() * 327749029));
let noiseBiomes = new Noise(Math.floor(PRNG() * 927472011));

let terrainCue = new NumberCue([0, 1, 2, 3, 3], [0.0, 0.45, 0.5, 0.9, 1.0]);
let terrainTintCue = new NumberCue([0.9, 1, 1, 0.95, 0.9, 1, 0.93, 1], [0.0, 0.45, 0.45, 0.5, 0.5, 0.9, 0.9, 1.0]);

/**
 * 
 * @param {WorldChunk} chunk chunk to fill
 * @param {Number} x ceiled coordinates of left-upper corner
 * @param {Number} y ceiled coordinates of left-upper corner
 */
export function fillWorldGenChunk(chunk, x, y) {
    let ii = 0;
    let jj = 0;
    for (let i = BC_CHUNKS_SETTINGS.width * x; i < BC_CHUNKS_SETTINGS.width * (x + 1); i++) {
        jj = 0;
        for (let j = BC_CHUNKS_SETTINGS.height * y; j < BC_CHUNKS_SETTINGS.height * (y + 1); j++) {
            let res = (noise.simplex2(i * 0.025, j * 0.025) + 1) / 2;
            let resR = (noiseErosion.simplex2(i * 0.3, j * 0.3) + 1) / 2;
            let resB = (noiseBiomes.simplex2(i * 0.01, j * 0.01) + 1) / 2;
            if (resB > 0.7) {
                res = clampNumber(res - resR / 4, 0.0, 0.99);
            }
            if (resB > 0.5 && res < 0.9 && res >= 0.5) {
                res = clampNumber(res + resR / 4, 0.0, 0.99);
            }

            let sTint = new RGBColor(255, 255, 255).multiplyByNumber(terrainTintCue.getValueAt(res)).toNumber();
            res = Math.floor(terrainCue.getValueAt(res));

            let terrainTile = new TerrainTile();
            terrainTile.spriteSheetPath = "assets/images/world/world_terrain_atlas.png";
            terrainTile.frame = new Rectangle(terrainSpriteList[res].x, terrainSpriteList[res].y, 16, 16);
            terrainTile.props = new TerrainTileProps(terrainTypeList[res], res*5);
            addGameObjectToGameState(terrainTile);

            terrainTile.drawObject.tint = sTint;
            terrainTile.drawObject.position.set(16 * BC_SPRITES_SETTINGS.scale * ii, 16 * BC_SPRITES_SETTINGS.scale * jj);
            terrainTile.drawObject.scale.set(BC_SPRITES_SETTINGS.scale, BC_SPRITES_SETTINGS.scale);

            chunk.addToChunk(terrainTile, ChunkStorageTypes.TYPE_TERRAIN, i+"_"+j);
            // let sprite = getSpriteFromAtlas(
            //     "assets/images/world/world_terrain_atlas.png",
            //     new PIXI.Rectangle(terrainSpriteList[res].x, terrainSpriteList[res].y, 16, 16)
            // );
            // sprite.position.set(16 * BC_SPRITES_SETTINGS.scale * ii, 16 * BC_SPRITES_SETTINGS.scale * jj);
            // sprite.scale.set(BC_SPRITES_SETTINGS.scale, BC_SPRITES_SETTINGS.scale);
            // sprite.tint = sTint;
            // addToTerrain(chunk, sprite, { type: terrainTypeList[res] }, i, j);
            // console.log(ii, jj);
            // addToTerrain(sprite, {x: i, y: j}, {type: terrainTypeList[res]});
            // if (res === 2 && PRNG() > 0.9) {
            //     let rv = Math.floor(PRNG() * 18);

            //     let veg = getSpriteFromAtlas(
            //         "assets/images/world/vegetation_ts.png",
            //         new PIXI.Rectangle(16 * grassVegetationSpriteList[rv].x, 16 * grassVegetationSpriteList[rv].y, 16, 16)
            //     );
            //     veg.position.set(16 * BC_SPRITES_SETTINGS.scale * ii, 16 * BC_SPRITES_SETTINGS.scale * jj);
            //     veg.scale.set(BC_SPRITES_SETTINGS.scale, BC_SPRITES_SETTINGS.scale);
            //     veg.tint = sTint;
            //     addToVegetation(chunk, veg, { ...grassVegResourcesList[rv] }, i, j);
            //     jj++;
            //     continue;
            // }
            // if (res === 1 && PRNG() > 0.99) {
            //     let rv = Math.floor(PRNG() * 6);

            //     let veg = getSpriteFromAtlas(
            //         "assets/images/world/vegetation_ts.png",
            //         new PIXI.Rectangle(16 * sandVegetationSpriteList[rv].x, 16 * sandVegetationSpriteList[rv].y, 16, 16)
            //     );
            //     veg.position.set(16 * BC_SPRITES_SETTINGS.scale * ii, 16 * BC_SPRITES_SETTINGS.scale * jj);
            //     veg.scale.set(BC_SPRITES_SETTINGS.scale, BC_SPRITES_SETTINGS.scale);
            //     veg.tint = sTint;
            //     addToVegetation(chunk, veg, { ...sandVegResourcesList[rv] }, i, j);
            //     jj++;
            //     continue;
            // }
            // if (res === 3 && PRNG() > 0.9) {
            //     let rv = Math.floor(PRNG() * 3);

            //     let veg = getSpriteFromAtlas(
            //         "assets/images/world/vegetation_ts.png",
            //         new PIXI.Rectangle(16 * stoneVegetationSpriteList[rv].x, 16 * stoneVegetationSpriteList[rv].y, 16, 16)
            //     );
            //     veg.position.set(16 * BC_SPRITES_SETTINGS.scale * ii, 16 * BC_SPRITES_SETTINGS.scale * jj);
            //     veg.scale.set(BC_SPRITES_SETTINGS.scale, BC_SPRITES_SETTINGS.scale);
            //     veg.tint = sTint;
            //     addToVegetation(chunk, veg, { ...stoneVegResourcesList[rv] }, i, j);
            //     jj++;
            //     continue;
            // }
            jj++;
        }
        ii++;
    }
}

export function createChunks() {
    let w = BC_CHUNKS_SETTINGS.width * BC_TERRAIN_SETTINGS.tileSize * BC_TERRAIN_SETTINGS.scale;
    let h = BC_CHUNKS_SETTINGS.height * BC_TERRAIN_SETTINGS.tileSize * BC_TERRAIN_SETTINGS.scale;
    for (let i = -1; i < 2; i++) {
        for (let j = -1; j < 2; j++) {
            let chunkXCeiled = Math.floor((BC_CAMERA.position.x + w * i) / w);
            let chunkYCeiled = Math.floor((BC_CAMERA.position.y + h * j) / h);
            let chunkId = chunkXCeiled + "_" + chunkYCeiled;

            let chunk = new WorldChunk(false);
            chunk.drawObject.position.set(w * chunkXCeiled, h * chunkYCeiled);

            BC_CURRENT_SCENE.addObjectToSceneWithInitialization(chunk);

            fillWorldGenChunk(chunk, chunkXCeiled, chunkYCeiled);
            WorldChunksStorage.set(chunkId, chunk);
            // console.log(chunkId);
            // let chunkRef = createWorldChunkContainer();
            // chunkRef.isRenderGroup = true;
            // chunkRef.position.set(w * chunkXCeiled, h * chunkYCeiled);
            // console.log(w * chunkXCeiled, h * chunkYCeiled);
            // let chunk0 = new WorldChunk(
            //     chunkRef,
            //     chunkRef.getChildAt(0),
            //     chunkRef.getChildAt(1),
            //     chunkRef.getChildAt(2),
            //     // chunkRef.getChildAt(3),
            //     new Vault("terrain"),
            //     new Vault("vegetation"),
            //     new Vault("buildings")
            // );

            // fillChunk(chunk0, chunkXCeiled, chunkYCeiled);
            // WORLD_CHUNKS.set(chunkId, chunk0);
            // chunkRef.visible = false;
            // addToViewport(chunkRef);
            // console.log(WORLD_CHUNKS)
            // console.log(chunkXCeiled, chunkYCeiled);
        }
    }
}

/* #### REWRITE PART END ####*/