import { stepDurationInMs } from "./Globals.js";
import { Level } from "./Level.js";


export type TileKind = "space" | "steel" | "sand" | "boulder" | "gemstone" | "wall" | "enemy1" | "wheel" | "enemy2" | "player" | "doortop" | "doorbottom";
export var Tilekinds: TileKind[] = ["space", "steel", "sand", "boulder", "gemstone", "wall", "enemy1", "wheel", "enemy2", "player", "doortop", "doorbottom"];

export type TileData = {
    name: string,
    char: string
}

/**
 * A Tile is a sprite with quadratic shape. Each Level consists of several tiles.
 */
export class Tile extends Phaser.Physics.Arcade.Sprite {

    isFalling: boolean = false;     // true if tile is boulder/gemstone and had been falling in last simulation step

    public static tiledata: Map<TileKind, TileData> = new Map([
        ["space", { name: null, char: " " }],
        ["steel", { name: 'Boulder#1', char: "e" }],
        ["sand", { name: 'Boulder#2', char: "s" }],
        ["boulder", { name: 'Boulder#3', char: "b" }],
        ["gemstone", { name: 'Boulder#4', char: "g" }],
        ["wall", { name: 'Boulder#5', char: "w" }],
        ["enemy1", { name: 'Boulder#6', char: "f" }],
        ["wheel", { name: 'Boulder#7', char: "a" }],
        ["enemy2", { name: 'Boulder#8', char: "F" }],
        ["player", { name: 'Boulder#9', char: "r" }],
        ["doortop", { name: 'Boulder#10', char: "d" }],
        ["doorbottom", { name: 'Boulder#11', char: "D" }]
    ]);

    constructor(scene: Phaser.Scene, public column: number, public row: number, public kind: TileKind, public level: Level) {

        super(scene, 0, 0, "spritesheet", Tile.tiledata.get(kind).name);
        this.scene.add.existing(this);

        this.setPosition(this.columnToX(column), this.rowToY(row));

    }

    /**
     * transforms column index to pixel-position on screen
     */
    columnToX(column: number): number {
        return 32 * column + 16;
    }

    /**
     * transforms row index to pixel-position on screen
     */
    rowToY(row: number): number {
        return 32 * row + 16;
    }

    /**
     * move tile slowly to given position and update tile-array in level and this.column, this.row.
     * 
     * If new position is bottom-left or bottom-right of current position 
     * then this method moves tile on a 1/4-circle-path.
     * @param column 
     * @param row 
     */
    goTo(column: number, row: number) {

        this.level.tiles[this.column][this.row] = null;
        this.level.tiles[column][row] = this;

        /**
         * If new position is bottom-left or bottom-right of current position 
         * then this method moves tile on a 1/4-circle-path.
         */
        if (Math.abs(column - this.column) == 1 && row - this.row == 1) {

            let x0 = this.columnToX(this.column);
            let y0 = this.rowToY(row);

            let leftRight = Math.sign(column - this.column);

            this.scene.tweens.add({
                targets: this,
                x: this.columnToX(column),
                y: this.rowToY(row),
                duration: stepDurationInMs,
                ease: "Linear",
                onUpdateScope: this,
                onUpdate: (tween, target, param) => {
                    // tween.totalProgress starts with value 0 and increases linearly with time to end-value 1.
                    let currentAngle = (1 - tween.totalProgress) * Math.PI / 2;    
                    this.setPosition(x0 + leftRight * Math.cos(currentAngle) * 32, y0 - Math.sin(currentAngle) * 32);
                }
            })
        } else {
            // otherwise: move linear
            this.scene.tweens.add({
                targets: this,
                x: this.columnToX(column),
                y: this.rowToY(row),
                duration: stepDurationInMs,
                ease: "Linear",
            })
        }

        this.column = column;
        this.row = row;

    }

}