import { Door } from "./Door.js";
import { Enemy1 } from "./Enemy1.js";
import { Enemy2 } from "./Enemy2.js";
import { Player } from "./Player.js";
import { Tile, Tilekinds } from "./Tile.js";
/**
 * Base class for all levels
 */
export class Level {
    constructor(mainScene) {
        this.mainScene = mainScene;
        this.initTileKinds(); // fills array initialTileKinds based on information about this specific level
    }
    /**
     * Fills array initialTileKinds based on level map in string[]-form.
     * @param leveldata
     */
    fromOriginalLeveldata(leveldata) {
        let oldIndexToTileKindMap = {};
        for (let k of Tilekinds) {
            let td = Tile.tiledata.get(k);
            oldIndexToTileKindMap[td.char] = k;
        }
        this.initialTileKinds = [];
        for (let column = 0; column < leveldata[0].length; column++) {
            this.initialTileKinds.push([]);
            for (let row = 0; row < leveldata.length; row++) {
                let s = leveldata[row];
                this.initialTileKinds[column].push(oldIndexToTileKindMap[s.charAt(column)]);
            }
        }
    }
    /**
     * Instantiates tile objects based on array initialTileKinds.
     */
    setupTiles() {
        if (this.tiles != null) {
            this.destroyTiles();
        }
        this.mainScene.cameras.main.setBounds(0, 0, this.initialTileKinds.length * 32, this.initialTileKinds[0].length * 32);
        this.tiles = [];
        this.numberOfGems = 0;
        for (let column = 0; column < this.initialTileKinds.length; column++) {
            this.tiles.push([]);
            for (let row = 0; row < this.initialTileKinds[column].length; row++) {
                let tk = this.initialTileKinds[column][row];
                if (tk == "space" || tk == null) {
                    this.tiles[column].push(null);
                    continue;
                }
                let tile;
                switch (tk) {
                    case "player":
                        tile = new Player(this.mainScene, column, row, this);
                        this.player = tile;
                        this.mainScene.cameras.main.startFollow(tile);
                        break;
                    case "enemy2":
                        tile = new Enemy2(this.mainScene, column, row, this);
                        break;
                    case "enemy1":
                        tile = new Enemy1(this.mainScene, column, row, this);
                        break;
                    case "doortop":
                        this.door = new Door(this.mainScene, column, row, this);
                        tile = this.door.doorTop;
                        this.tiles[column].push(this.door.doorTop);
                        this.tiles[column].push(this.door.doorBottom);
                        row++;
                        continue;
                    default:
                        tile = new Tile(this.mainScene, column, row, tk, this);
                        if (tk == "gemstone") {
                            this.numberOfGems++;
                        }
                        break;
                }
                this.tiles[column].push(tile);
            }
        }
        if (this.player != null) {
            this.mainScene.children.bringToTop(this.player);
        }
        this.mainScene.getScoreBoard().setGems(this.numberOfGems);
    }
    destroyTiles() {
        for (let tc of this.tiles) {
            for (let tr of tc) {
                if (tr != null) {
                    tr.destroy();
                }
            }
        }
        this.tiles = null;
    }
    /**
     * This method is called from MainScene.update every simulation-step. It's purpose is to
     * make boulders and gems fall.
     * @returns
     */
    simulateFallingBouldersAndGems() {
        // Begin with bottommost-row and work upwards:
        for (let row = this.tiles[0].length - 1; row >= 0; row--) {
            for (let column = 0; column < this.tiles.length; column++) {
                let tile = this.tiles[column][row];
                if (tile == null)
                    continue;
                // Is there a boulder or gemstone?
                if (tile.kind == "boulder" || tile.kind == "gemstone") {
                    // characters a to f in subsequent code denote positions adjacent to current tile.
                    // Current tile is (boulder/gemstone) is at position b.
                    // abc
                    // def
                    let tileE = this.tiles[column][row + 1];
                    // nothing directly below boulder/gemstone? => Let it fall!
                    if (tileE == null) {
                        tile.isFalling = true;
                        tile.goTo(column, row + 1);
                        continue;
                    }
                    else {
                        if (tileE == this.player && tile.isFalling) {
                            this.lifeLost();
                            return;
                        }
                        // boulder or gemstone directly below? 
                        // => check if position right/left and bottom-right/bottom-left is empty so that
                        //    boulder/gemstone can roll sidewards:
                        if (tileE.kind == "boulder" || tileE.kind == "gemstone") {
                            let tileC = this.tiles[column + 1][row];
                            if (tileC == null) {
                                let tileF = this.tiles[column + 1][row + 1];
                                if (tileF == this.player && tile.isFalling) {
                                    this.lifeLost();
                                    return;
                                }
                                if (tileF == null) {
                                    tile.isFalling = true;
                                    tile.goTo(column + 1, row + 1);
                                    continue;
                                }
                            }
                            let tilea = this.tiles[column - 1][row];
                            if (tilea == null) {
                                let tiled = this.tiles[column - 1][row + 1];
                                if (tiled == this.player && tile.isFalling) {
                                    this.lifeLost();
                                    return;
                                }
                                if (tiled == null) {
                                    tile.isFalling = true;
                                    tile.goTo(column - 1, row + 1);
                                    continue;
                                }
                            }
                        }
                    }
                    tile.isFalling = false;
                }
            }
        }
    }
    lifeLost() {
        this.mainScene.gameOver();
    }
}
//# sourceMappingURL=Level.js.map