import { Container, Ticker } from "pixi.js";
import { Tile } from "./parts/Tile";
import { Wall } from "./parts/Wall";
import { Stair } from "./parts/Stair";
import { WallType } from "../../enums/WallType";
import { Cursor } from "./parts/Cursor";
import { RoomObjectLayer } from "./layers/RoomObjectLayer";
import { RoomTileLayer } from "./layers/RoomTileLayer";
/**
 * RoomView class that manage all the rendering part of the room.
 *
 * @class
 * @memberof Scuti
 */
export class RoomView extends Container {
    /**
     * @param {Room} [room] - The room instance that we want to visualize.
     */
    constructor(room) {
        super();
        /**
         * The container that will contains all the walls objects.
         *
         * @member {Container}
         * @private
         */
        this._wallLayer = new Container();
        /**
         * List containing all the walls instances.
         *
         * @member {Wall}
         * @private
         */
        this._walls = [];
        /**
         * List containing all the tiles and stairs instances.
         *
         * @member {Tile | Stair}
         * @private
         */
        this._tiles = [];
        /**
         * The room animation ticker instance that will manage all the objects animations
         *
         * @member {Ticker}
         * @private
         */
        this._animationTicker = new Ticker();
        this._room = room;
        this._tileLayer = new RoomTileLayer(this._room);
        this._objectLayer = new RoomObjectLayer(this._room);
        /** Add layers to the visualization */
        this.addChild(this._wallLayer);
        this.addChild(this._tileLayer);
        this.addChild(this._objectLayer);
        /** Start the animation ticker */
        //this._animationTicker.maxFPS = 15.666;
        this._animationTicker.maxFPS = 4;
        this._animationTicker.start();
        /** Render everything */
        this._draw();
    }
    /**
     * Draw the room visualization with all the tiles and walls.
     *
     * @return {void}
     * @private
     */
    _draw() {
        this._destroyParts();
        for (let y = 0; y < this._room.tileMap.tileMap.length; y++) {
            for (let x = 0; x < this._room.tileMap.tileMap[y].length; x++) {
                const tileInfo = this._room.tileMap.getTileInfo({
                    x: x,
                    y: y
                });
                this._createPart(tileInfo, {
                    x: x,
                    y: y,
                    z: tileInfo.height
                });
            }
        }
    }
    /**
     * Destroy all the parts (tiles, walls, stairs, ...).
     *
     * @return {void}
     * @private
     */
    _destroyParts() {
        [...this._tiles, ...this._walls].forEach((part) => part.destroy());
        this._tiles = [];
        this._walls = [];
    }
    /**
     * Rerender all the room visualization.
     *
     * @return {void}
     * @private
     */
    update() {
        this._draw();
    }
    /**
     * Create a room part and add it into the visualization.
     *
     * @param {ITileInfo} [tileInfo] - The tile informations where we want to create the part.
     * @param {IPosition3D} [position] - And the position.
     * @return {void}
     * @private
     */
    _createPart(tileInfo, position) {
        if (tileInfo.wallType !== null || tileInfo.door) {
            if (tileInfo.wallType === WallType.CORNER_WALL && !this._room.tileMap.hasWall(position).x && !this._room.tileMap.hasWall(position).y) {
                this._createWall(position, WallType.CORNER_WALL);
                this._createWall(position, WallType.LEFT_WALL);
                this._createWall(position, WallType.RIGHT_WALL);
            }
            else if (tileInfo.wallType === WallType.CORNER_WALL && !this._room.tileMap.hasWall(position).x) {
                this._createWall(position, WallType.LEFT_WALL);
            }
            else if (tileInfo.wallType === WallType.CORNER_WALL && !this._room.tileMap.hasWall(position).y) {
                this._createWall(position, WallType.RIGHT_WALL);
            }
            if (tileInfo.wallType === WallType.LEFT_WALL && !this._room.tileMap.hasWall(position).x)
                this._createWall(position, WallType.LEFT_WALL);
            if (tileInfo.wallType === WallType.RIGHT_WALL && !this._room.tileMap.hasWall(position).y)
                this._createWall(position, WallType.RIGHT_WALL);
            if (tileInfo.door)
                this._createWall(position, WallType.DOOR_WALL);
        }
        if (tileInfo.stairType !== null) {
            position.direction = tileInfo.stairType.direction;
            this._createStair(position, tileInfo.stairType.type);
        }
        else if (tileInfo.door) {
            this._createDoor(position);
        }
        else if (tileInfo.tile) {
            this._createTile(position, tileInfo);
        }
    }
    /**
     * Destroy the current cursor and draw a new one at the new position.
     *
     * @param {IPosition3D} [position] - The cursor position.
     * @return {void}
     * @private
     */
    _createCursor(position) {
        if (this._cursor) {
            this._cursor.visible = true;
            this._cursor.moveTo(position);
            return;
        }
        this._destroyCursor();
        const cursor = new Cursor(this._room, {
            position: position
        });
        this._objectLayer.addChild(cursor);
        this._cursor = cursor;
    }
    /**
     * Destroy the room cursor
     *
     * @return {void}
     * @private
     */
    _destroyCursor() {
        if (this._cursor) {
            this._cursor.visible = false;
        }
    }
    /**
     * Create a tile.
     *
     * @param {IPosition3D} [position] - The tile position.
     * @return {void}
     * @private
     */
    _createTile(position, tileInfo) {
        const tile = new Tile(this._room, {
            position: position,
            material: this._room.floorMaterial,
            thickness: this._room.floorThickness
        }, tileInfo);
        /** Register interactions */
        tile.onPointerDown = (event) => { if (this._tileLayer.onPointerDown)
            this._tileLayer.onPointerDown(event); };
        tile.onPointerUp = (event) => { if (this._tileLayer.onPointerUp)
            this._tileLayer.onPointerUp(event); };
        tile.onPointerMove = (event) => { if (this._tileLayer.onPointerMove)
            this._tileLayer.onPointerMove(event); };
        tile.onPointerOut = (event) => { if (this._tileLayer.onPointerOut)
            this._tileLayer.onPointerOut(event); this._destroyCursor(); };
        tile.onPointerOver = (event) => { if (this._tileLayer.onPointerOver)
            this._tileLayer.onPointerOver(event); this._createCursor(position); };
        tile.onDoubleClick = (event) => { if (this._tileLayer.onDoubleClick)
            this._tileLayer.onDoubleClick(event); };
        this._tileLayer.addChild(tile);
        this._tiles.push(tile);
    }
    /**
     * Create a door.
     *
     * @param {IPosition3D} [position] - The door position.
     * @return {void}
     * @private
     */
    _createDoor(position) {
        const tile = new Tile(this._room, {
            position: position,
            material: this._room.floorMaterial,
            thickness: 0
        });
        /** Register interactions */
        tile.onPointerDown = (event) => { if (this._tileLayer.onPointerDown)
            this._tileLayer.onPointerDown(event); };
        tile.onPointerUp = (event) => { if (this._tileLayer.onPointerUp)
            this._tileLayer.onPointerUp(event); };
        tile.onPointerMove = (event) => { if (this._tileLayer.onPointerMove)
            this._tileLayer.onPointerMove(event); };
        tile.onPointerOut = (event) => { if (this._tileLayer.onPointerOut)
            this._tileLayer.onPointerOut(event); this._destroyCursor(); };
        tile.onPointerOver = (event) => { if (this._tileLayer.onPointerOver)
            this._tileLayer.onPointerOver(event); this._createCursor(position); };
        tile.onDoubleClick = (event) => { if (this._tileLayer.onDoubleClick)
            this._tileLayer.onDoubleClick(event); };
        this._tileLayer.addChild(tile);
        this._tiles.push(tile);
    }
    /**
     * Create a wall.
     *
     * @param {IPosition3D} [position] - The wall position.
     * @param {WallType} [type] - The wall type.
     * @return {void}
     * @private
     */
    _createWall(position, type) {
        const wall = new Wall(this._room, {
            position: position,
            material: this._room.wallMaterial,
            thickness: this._room.wallThickness,
            height: this._room.wallHeight,
            type: type
        });
        this._wallLayer.addChild(wall);
        this._walls.push(wall);
    }
    /**
     * Create stairs.
     *
     * @param {IPosition3D} [position] - The stairs position.
     * @param {StairType} [type] - The stairs type.
     * @return {void}
     * @private
     */
    _createStair(position, type) {
        const stair = new Stair(this._room, {
            position: position,
            material: this._room.floorMaterial,
            thickness: this._room.floorThickness,
            type: type
        });
        /** Register interactions */
        stair.onPointerDown = (event) => { if (this._tileLayer.onPointerDown)
            this._tileLayer.onPointerDown(event); };
        stair.onPointerUp = (event) => { if (this._tileLayer.onPointerUp)
            this._tileLayer.onPointerUp(event); };
        stair.onPointerMove = (event) => { if (this._tileLayer.onPointerMove)
            this._tileLayer.onPointerMove(event); };
        stair.onPointerOut = (event) => { if (this._tileLayer.onPointerOut)
            this._tileLayer.onPointerOut(event); this._destroyCursor(); };
        stair.onPointerOver = (event) => { if (this._tileLayer.onPointerOver)
            this._tileLayer.onPointerOver(event); this._createCursor(position); };
        stair.onDoubleClick = (event) => { if (this._tileLayer.onDoubleClick)
            this._tileLayer.onDoubleClick(event); };
        this._tileLayer.addChild(stair);
        this._tiles.push(stair);
    }
    /**
     * Reference to the room visualization room instance.
     *
     * @member {Room}
     * @readonly
     * @public
     */
    get room() {
        return this._room;
    }
    /**
     * Reference to the tile layer container.
     *
     * @member {RoomTileLayer}
     * @readonly
     * @public
     */
    get tileLayer() {
        return this._tileLayer;
    }
    /**
     * Reference to the wall layer container.
     *
     * @member {Container}
     * @readonly
     * @public
     */
    get wallLayer() {
        return this._wallLayer;
    }
    /**
     * Reference to the object layer container.
     *
     * @member {RoomObjectLayer}
     * @readonly
     * @public
     */
    get objectLayer() {
        return this._objectLayer;
    }
    /**
     * Reference to the room animation ticker instance.
     *
     * @member {Ticker}
     * @readonly
     * @public
     */
    get animationTicker() {
        return this._animationTicker;
    }
}
//# sourceMappingURL=RoomView.js.map