import { Container, Graphics, Matrix, Point, Polygon, utils } from "pixi.js";
import { FloorMaterial } from "../materials/FloorMaterial";
import { InteractionManager } from "../../interactions/InteractionManager";
/**
 * Tile class that show up during room rendering.
 *
 * @class
 * @memberof Scuti
 */
export class Tile extends Container {
    /**
     * @param {Room} [room] - The room instance where the tile will be drawn.
     * @param {ITileConfiguration} [configuration] - The tile configuration.
     * @param {Material} [configuration.material] - The time material that will be applied.
     * @param {number} [configuration.thickness] - The tile thickness.
     * @param {IPosition3D} [configuration.position] - The tile position.
     **/
    constructor(room, configuration, tileInfo) {
        var _a, _b;
        super();
        /**
         * The tile interaction manager.
         *
         * @member {InteractionManager}
         * @private
         */
        this._interactionManager = new InteractionManager();
        /** Store the configuration */
        this._room = room;
        this._tileInfo = tileInfo;
        this._position = configuration.position;
        this._thickness = (_a = configuration.thickness) !== null && _a !== void 0 ? _a : 8;
        this._material = (_b = configuration.material) !== null && _b !== void 0 ? _b : new FloorMaterial(this._room.engine, 111);
        /** Register interactions */
        this.on("pointerdown", (event) => this._interactionManager.handlePointerDown({ mouseEvent: event, position: this._position }));
        this.on("pointerup", (event) => this._interactionManager.handlePointerUp({ mouseEvent: event, position: this._position }));
        this.on("pointermove", (event) => this._interactionManager.handlePointerMove({ mouseEvent: event, position: this._position }));
        this.on("pointerout", (event) => this._interactionManager.handlePointerOut({ mouseEvent: event, position: this._position }));
        this.on("pointerover", (event) => this._interactionManager.handlePointerOver({ mouseEvent: event, position: this._position }));
        // TODO: Make the method public and use it when adding it to a room, not when instancing the class
        /** Draw the tile */
        this._draw();
    }
    /**
     * Draw the tile.
     *
     * @return {void}
     * @private
     */
    _draw() {
        /** Top face */
        const top = new Graphics()
            .beginTextureFill({
            texture: this._material.texture,
            color: utils.premultiplyTint(this._material.color, 1),
            //matrix: new Matrix(1, 0.5, 1, -0.5, (this._position.x % 2 === 0 || this._position.y % 2 === 0) && !(this._position.x % 2 === 0 && this._position.y % 2 === 0) ? 32 : 0, (this._position.x % 2 === 0 || this._position.y % 2 === 0) && !(this._position.x % 2 === 0 && this._position.y % 2 === 0) ? 16 : 0)
            matrix: new Matrix(1, 0.5, 1, -0.5, (this._position.y % 2 === 0) ? 32 : 64, (this._position.y % 2 === 0) ? 16 : 0)
        })
            .moveTo(0, 0)
            .lineTo(32, -16)
            .lineTo(64, 0)
            .lineTo(32, 16)
            .lineTo(0, 0)
            .endFill();
        this.addChild(top);
        let bottomTile;
        let rightTile;
        if (this._room.tileMap.tileMap[this._position.y + 1][this._position.x] !== undefined) {
            bottomTile = this._room.tileMap.getTileInfo({ x: this._position.x, y: this._position.y + 1 });
        }
        if (typeof this._room.tileMap.tileMap[this._position.y][this._position.x + 1] !== "undefined") {
            rightTile = this._room.tileMap.getTileInfo({ x: this._position.x + 1, y: this._position.y });
        }
        if (!bottomTile || bottomTile.stairType !== null || !bottomTile.tile || (this._tileInfo && bottomTile.height != this._tileInfo.height)) {
            /** Left face */
            const left = new Graphics()
                .beginTextureFill({
                texture: this._material.texture,
                color: utils.premultiplyTint(this._material.color, 0.8),
                matrix: new Matrix(1, 0.5, 0, 1, 0, 0)
            })
                .moveTo(0, 0)
                .lineTo(0, this._thickness)
                .lineTo(32, 16 + this._thickness)
                .lineTo(32, 16)
                .endFill();
            this.addChild(left);
        }
        if (!rightTile || rightTile.stairType !== null || !rightTile.tile || (this._tileInfo && rightTile.height != this._tileInfo.height)) {
            /** Right face */
            const right = new Graphics()
                .beginTextureFill({
                texture: this._material.texture,
                color: utils.premultiplyTint(this._material.color, 0.71),
                matrix: new Matrix(1, -0.5, 0, 1, 0, 0)
            })
                .moveTo(32, 16)
                .lineTo(32, 16 + this._thickness)
                .lineTo(64, this._thickness)
                .lineTo(64, 0)
                .lineTo(32, 16)
                .endFill();
            this.addChild(right);
        }
        /** Positionate the wall */
        this.x = 32 * this._position.x - 32 * this._position.y;
        this.y = 16 * this._position.x + 16 * this._position.y - 32 * this._position.z;
        /** Set the hit area */
        this.hitArea = new Polygon(new Point(0, 0), new Point(32, -16), new Point(64, 0), new Point(32, 16), new Point(0, 0));
    }
    /**
     * Reference to the tile thickness.
     *
     * @member {number}
     * @readonly
     * @public
     */
    get thickness() {
        return this._thickness;
    }
    /**
     * Update the tile thickness and redraw the tile.
     *
     * @param {number} [thickness] - The room tile thickness that will be applied.
     * @public
     */
    set thickness(thickness) {
        this._thickness = thickness;
        /** Redraw the tile */
        this._draw();
    }
    /**
     * Reference to the tile material instance.
     *
     * @member {Material}
     * @readonly
     * @public
     */
    get material() {
        return this._material;
    }
    /**
     * Update the tile material and redraw the tile.
     *
     * @param {Material} [material] - The room tile material that will be applied.
     * @public
     */
    set material(material) {
        this._material = material;
        /** Redraw the tile */
        this._draw();
    }
    /**
     * Reference to the pointer down event.
     *
     * @member {(event: IInteractionEvent) => void}
     * @readonly
     * @public
     */
    get onPointerDown() {
        return this._interactionManager.onPointerDown;
    }
    /**
     * Update the event function that will be executed.
     *
     * @param {(event: IInteractionEvent) => void} [value] - The event function that will be executed.
     * @public
     */
    set onPointerDown(value) {
        this._interactionManager.onPointerDown = value;
    }
    /**
     * Reference to the pointer up event.
     *
     * @member {(event: IInteractionEvent) => void}
     * @readonly
     * @public
     */
    get onPointerUp() {
        return this._interactionManager.onPointerUp;
    }
    /**
     * Update the event function that will be executed.
     *
     * @param {(event: IInteractionEvent) => void} [value] - The event function that will be executed.
     * @public
     */
    set onPointerUp(value) {
        this._interactionManager.onPointerUp = value;
    }
    /**
     * Reference to the pointer move event.
     *
     * @member {(event: IInteractionEvent) => void}
     * @readonly
     * @public
     */
    get onPointerMove() {
        return this._interactionManager.onPointerMove;
    }
    /**
     * Update the event function that will be executed.
     *
     * @param {(event: IInteractionEvent) => void} [value] - The event function that will be executed.
     * @public
     */
    set onPointerMove(value) {
        this._interactionManager.onPointerMove = value;
    }
    /**
     * Reference to the pointer out event.
     *
     * @member {(event: IInteractionEvent) => void}
     * @readonly
     * @public
     */
    get onPointerOut() {
        return this._interactionManager.onPointerOut;
    }
    /**
     * Update the event function that will be executed.
     *
     * @param {(event: IInteractionEvent) => void} [value] - The event function that will be executed.
     * @public
     */
    set onPointerOut(value) {
        this._interactionManager.onPointerOut = value;
    }
    /**
     * Reference to the pointer over event.
     *
     * @member {(event: IInteractionEvent) => void}
     * @readonly
     * @public
     */
    get onPointerOver() {
        return this._interactionManager.onPointerOver;
    }
    /**
     * Update the event function that will be executed.
     *
     * @param {(event: IInteractionEvent) => void} [value] - The event function that will be executed.
     * @public
     */
    set onPointerOver(value) {
        this._interactionManager.onPointerOver = value;
    }
    /**
     * Reference to the pointer double click event.
     *
     * @member {(event: IInteractionEvent) => void}
     * @readonly
     * @public
     */
    get onDoubleClick() {
        return this._interactionManager.onDoubleClick;
    }
    /**
     * Update the event function that will be executed.
     *
     * @param {(event: IInteractionEvent) => void} [value] - The event function that will be executed.
     * @public
     */
    set onDoubleClick(value) {
        this._interactionManager.onDoubleClick = value;
    }
}
//# sourceMappingURL=Tile.js.map