"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
const BlockCubePlane_1 = require("./BlockCubePlane");
const ste_events_1 = require("ste-events");
const Entity_1 = require("./Entity");
const Log_1 = require("../core/Log");
class BlockCube {
    _maxX = 1;
    _maxY = 1;
    _maxZ = 1;
    _onMaxDimensionsChanged = new ste_events_1.EventDispatcher();
    _onBlockTypeChanged = new ste_events_1.EventDispatcher();
    _onBlockPropertyChanged = new ste_events_1.EventDispatcher();
    _columns;
    get onMaxDimensionsChanged() {
        return this._onMaxDimensionsChanged.asEvent();
    }
    get onBlockTypeChanged() {
        return this._onBlockTypeChanged.asEvent();
    }
    get onBlockPropertyChanged() {
        return this._onBlockPropertyChanged.asEvent();
    }
    get columns() {
        if (this._columns === undefined) {
            this._columns = this._generateColumnInfo();
        }
        return this._columns;
    }
    get maxX() {
        return this._maxX;
    }
    get maxY() {
        return this._maxY;
    }
    get maxZ() {
        return this._maxZ;
    }
    set maxX(newMaxX) {
        this._maxX = newMaxX;
        this._onMaxDimensionsChanged.dispatch(this, "x");
    }
    set maxY(newMaxY) {
        this._maxY = newMaxY;
        this._onMaxDimensionsChanged.dispatch(this, "y");
    }
    set maxZ(newMaxZ) {
        this._maxZ = newMaxZ;
        this._onMaxDimensionsChanged.dispatch(this, "z");
    }
    setMaxDimensions(newMaxX, newMaxY, newMaxZ) {
        this._maxX = newMaxX;
        this._maxY = newMaxY;
        this._maxZ = newMaxZ;
        this._onMaxDimensionsChanged.dispatch(this, "xyz");
    }
    planes;
    constructor() {
        this.planes = [];
    }
    spawnEntity(entityTypeId, location) {
        const e = new Entity_1.default();
        return e;
    }
    getBlock(location) {
        Log_1.default.assert(location.x >= 0 &&
            location.x <= this.maxX &&
            location.y >= 0 &&
            location.x <= this.maxY &&
            location.z >= 0 &&
            location.z <= this.maxZ, "Block location not within bounds.");
        return this.x(location.x).y(location.y).z(location.z);
    }
    getCommandList(fromX, fromY, fromZ) {
        const commands = [];
        for (let x = 0; x < this.maxX; x++) {
            for (let y = 0; y < this.maxY; y++) {
                for (let z = 0; z < this.maxZ; z++) {
                    const block = this.x(x).y(y).z(z);
                    if (!block.isEmpty) {
                        commands.push("setblock ~" + (fromX + x) + " ~" + (fromY + y) + " ~" + (fromZ + z) + " " + block.typeName);
                    }
                }
            }
        }
        return commands;
    }
    _generateColumnInfo() {
        const newColumns = new Array(this.maxZ);
        for (let z = 0; z < this.maxY; z++) {
            newColumns[z] = new Array(this.maxX);
            for (let x = 0; x < this.maxX; x++) {
                const blockX = this.x(x);
                let foundOpaqueTop = false;
                let foundContiguousTop = false;
                let opaqueTop = 0;
                let contiguousTop = 0;
                let top = 0;
                for (let y = 0; z < this.maxY; y++) {
                    const block = blockX.y(y).z(z);
                    if (!block.isEmpty && block.isOpaque && !foundOpaqueTop) {
                        opaqueTop++;
                    }
                    else if (!block.isEmpty) {
                        if (!foundContiguousTop) {
                            contiguousTop++;
                        }
                        top = y;
                        if (!block.isOpaque) {
                            foundOpaqueTop = true;
                        }
                    }
                    else {
                        foundOpaqueTop = true;
                        foundContiguousTop = true;
                    }
                }
                newColumns[x][z] = {
                    contiguousHeight: contiguousTop,
                    height: top,
                    opaqueHeight: opaqueTop,
                };
            }
        }
        return newColumns;
    }
    _notifyBlockTypeChanged(block) {
        this._columns = undefined;
        this._onBlockTypeChanged.dispatch(this, block);
    }
    _notifyBlockPropertyChanged(block) {
        this._onBlockPropertyChanged.dispatch(this, block);
    }
    x(int) {
        if (int > this.maxX) {
            throw new Error("Value exceeds maximum X");
        }
        while (int >= this.planes.length) {
            const newX = this.planes.length;
            this.planes[newX] = new BlockCubePlane_1.default(this, newX);
        }
        return this.planes[int];
    }
    fillEmpty(blockTypeId, xFrom, yFrom, zFrom, xTo, yTo, zTo) {
        for (let x = xFrom; x <= xTo; x++) {
            for (let y = yFrom; y <= yTo; y++) {
                let block = this.x(x).y(y).z(zFrom);
                block.typeName = blockTypeId;
                block = this.x(x).y(y).z(zTo);
                block.typeName = blockTypeId;
            }
        }
        for (let y = yFrom; y <= yTo; y++) {
            for (let z = zFrom + 1; z < zTo; z++) {
                let block = this.x(xFrom).y(y).z(z);
                block.typeName = blockTypeId;
                block = this.x(xTo).y(y).z(z);
                block.typeName = blockTypeId;
            }
        }
    }
    fill(blockTypeId, xFrom, yFrom, zFrom, xTo, yTo, zTo) {
        for (let x = xFrom; x <= xTo; x++) {
            for (let y = yFrom; y <= yTo; y++) {
                for (let z = zFrom; z <= zTo; z++) {
                    const block = this.x(x).y(y).z(z);
                    block.typeName = blockTypeId;
                }
            }
        }
    }
    fillY(blockTypeId, y) {
        for (let x = 0; x < this.maxX; x++) {
            const zSlice = this.x(x).y(y);
            for (let z = 0; z < this.maxZ; z++) {
                const block = zSlice.z(z);
                block.typeName = blockTypeId;
            }
        }
    }
}
exports.default = BlockCube;

//# sourceMappingURL=../maps/minecraft/BlockCube.js.map
