"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
const BlockRenderType_1 = require("./BlockRenderType");
const MinecraftUtilities_1 = require("./MinecraftUtilities");
const Database_1 = require("./Database");
const Utilities_1 = require("../core/Utilities");
const ste_events_1 = require("ste-events");
const Log_1 = require("../core/Log");
const ManagedComponent_1 = require("./ManagedComponent");
const StorageUtilities_1 = require("../storage/StorageUtilities");
const BLOCK_TYPE_MATERIALS = [
    "bone",
    "cobblestone",
    "stone",
    "andesite",
    "bedrock",
    "blackstone",
    "basalt",
    "acacia",
    "oak",
    "gold",
    "jungle",
    "birch",
    "big_oak",
    "spruce",
    "bamboo",
    "chiseled_nether_bricks",
    "chiseled_polished_blackstone_brick",
    "cracked_netherbricks",
    "cracked_polishedblackstone_bricks",
    "end_brick",
    "wood",
    "purpur",
    "brick",
    "blue",
    "black",
    "brown",
    "cyan",
    "gray",
    "light_blue",
    "lime",
    "magenta",
    "orange",
    "pink",
    "purple",
    "red",
    "silver",
    "white",
    "yellow",
    "fern",
    "grass",
    "paeonia",
    "rose",
    "rose_blue",
    "sunflower",
    "syringa",
    "allium",
    "blue_orchid",
    "cornflower",
    "dandelion",
    "houstonia",
    "lily_of_the_valley",
    "oxeye_daisy",
    "orange_tulip",
    "pink_tulip",
    "red_tulip",
    "white_tulip",
    "dark_oak",
    "blue_ice",
    "frosted_ice",
    "ice",
];
class BlockType {
    _typeId = "";
    data;
    javaData;
    _baseType;
    _baseTypeId = "";
    _material = "";
    _isCustom = false;
    _behaviorPackData = null;
    _behaviorPackFile;
    _id;
    _isLoaded = false;
    behaviorPackBlockTypeDef;
    _managed = {};
    _onLoaded = new ste_events_1.EventDispatcher();
    _onComponentAdded = new ste_events_1.EventDispatcher();
    _onComponentRemoved = new ste_events_1.EventDispatcher();
    _onComponentChanged = new ste_events_1.EventDispatcher();
    get numericId() {
        return this.data.id;
    }
    get baseTypeId() {
        return this._baseTypeId;
    }
    get mapColor() {
        return this.data.mapColor;
    }
    get isCustom() {
        return this._isCustom;
    }
    get baseType() {
        if (this._baseType !== undefined) {
            return this._baseType;
        }
        return Database_1.default.defaultBlockBaseType;
    }
    set baseType(baseType) {
        this._baseType = baseType;
        this._baseTypeId = baseType.name;
    }
    get material() {
        return this._material;
    }
    renderType = BlockRenderType_1.BlockRenderType.Custom;
    get icon() {
        let val = this.data.icon;
        if (val === undefined && this.baseType !== undefined) {
            val = this.baseType.icon;
        }
        return val;
    }
    get typeId() {
        return this._typeId;
    }
    get shortTypeName() {
        let name = this._typeId;
        const colonIndex = name.indexOf(":");
        if (colonIndex >= 0) {
            name = name.substring(colonIndex + 1, name.length);
        }
        return name;
    }
    get title() {
        const id = this.shortTypeName;
        return Utilities_1.default.humanifyMinecraftName(id);
    }
    constructor(name) {
        this._typeId = name;
        this.javaData = null;
        this.data = {
            name: name,
        };
        if (name.indexOf(":") >= 0 && !name.startsWith("minecraft:")) {
            this._isCustom = true;
        }
        const baseTypeShort = MinecraftUtilities_1.default.canonicalizeName(name);
        for (const material of BLOCK_TYPE_MATERIALS) {
            if (baseTypeShort.indexOf(material) >= 0) {
                this._material = material;
                break;
            }
        }
    }
    getIcon() {
        const icon = this.icon;
        if (icon === undefined) {
            return this.shortTypeName;
        }
        const typeName = MinecraftUtilities_1.default.canonicalizeName(this.shortTypeName);
        const lastUnder = typeName.lastIndexOf("_");
        let allButLast = typeName;
        if (lastUnder >= 0) {
            allButLast = allButLast.substring(0, lastUnder);
        }
        switch (icon) {
            case "st_":
                return "stone_" + allButLast;
            case "le_":
                return "leaves_acacia_carried";
            case "pl_":
                return "planks_" + allButLast;
            case "_car":
                return allButLast + "_carried";
            case "plant_":
                return typeName + "_fern_carried";
            case "_":
                return typeName;
            case "_t":
                return allButLast + "_top";
            case "_br":
                return allButLast + "_bricks";
            case "_carr":
                return typeName + "_carried";
            case "_bl":
                return allButLast + "_block";
            case "_n":
                return allButLast + "_normal";
            case "_blt":
                return allButLast + "_block_top";
            case "mshblk":
                const lastmb = allButLast.split("_");
                return "mushroom_block_skin_" + lastmb[0];
            case "ml_sm":
                const lastml = allButLast.split("_");
                return lastml[lastml.length - 2] + "_" + lastml[lastml.length - 1] + "_smooth";
            case "l_blt":
                const lastbt = allButLast.split("_");
                return lastbt[lastbt.length - 1] + "_block_top";
            case "|":
                return allButLast;
            case "|s":
                return allButLast + "s";
            case "l":
                const last = allButLast.split("_");
                return last[last.length - 1];
            case "sb_":
                const fu = allButLast.split("_");
                return "stonebricks_" + fu[0];
            case "st_l_sm":
                const lasta = allButLast.split("_");
                return "stone_" + lasta[lasta.length - 1] + "_smooth";
            case "|rv":
                // dark_prismarine_stairs => prismarine_dark_stairs
                let result = "";
                const rv = allButLast.split("_");
                for (let i = rv.length - 1; i > 0; i--) {
                    if (result.length > 0) {
                        result += "_";
                    }
                    result += rv[i];
                }
                return result;
            case "2rv":
                // yellow_glazed_terracotta => glazed_terracotta_yellow
                // dark_blue_glazed_terracotta => glazed_terracotta_dark_blue
                let resultF = "";
                const rvF = typeName.split("_");
                if (rvF.length >= 2) {
                    resultF = rvF[rvF.length - 2] + "_" + rvF[rvF.length - 1];
                    for (let i = 0; i < rvF.length - 2; i++) {
                        resultF += "_" + rvF[i];
                    }
                }
                else {
                    resultF = typeName;
                }
                return resultF;
            case "rv":
                // dark_prismarine => prismarine_dark
                let resultA = "";
                const rvA = typeName.split("_");
                for (let i = rvA.length - 1; i >= 0; i--) {
                    if (resultA.length > 0) {
                        resultA += "_";
                    }
                    resultA += rvA[i];
                }
                return resultA;
        }
        if (this.icon !== undefined) {
            return this.icon;
        }
        return this.shortTypeName;
    }
    get id() {
        if (this.behaviorPackBlockTypeDef && this.behaviorPackBlockTypeDef.description) {
            return this.behaviorPackBlockTypeDef.description.identifier;
        }
        if (this._id === undefined) {
            return "";
        }
        return this._id;
    }
    set id(newId) {
        this._id = newId;
        if (this.behaviorPackBlockTypeDef && this.behaviorPackBlockTypeDef.description && newId) {
            this.behaviorPackBlockTypeDef.description.identifier = newId;
        }
    }
    get onComponentAdded() {
        return this._onComponentAdded.asEvent();
    }
    get onComponentRemoved() {
        return this._onComponentRemoved.asEvent();
    }
    get onComponentChanged() {
        return this._onComponentChanged.asEvent();
    }
    get isLoaded() {
        return this._isLoaded;
    }
    get behaviorPackFile() {
        return this._behaviorPackFile;
    }
    get onLoaded() {
        return this._onLoaded.asEvent();
    }
    set behaviorPackFile(newFile) {
        this._behaviorPackFile = newFile;
    }
    get shortId() {
        if (this._id !== undefined) {
            if (this._id.startsWith("minecraft:")) {
                return this._id.substring(10, this._id.length);
            }
            return this._id;
        }
        return undefined;
    }
    getComponent(id) {
        if (this.behaviorPackBlockTypeDef === undefined) {
            return undefined;
        }
        if (!Utilities_1.default.isUsableAsObjectKey(id)) {
            Log_1.default.unsupportedToken(id);
            throw new Error();
        }
        if (!this._managed[id]) {
            const comp = this.behaviorPackBlockTypeDef.components[id];
            if (comp) {
                this._managed[id] = new ManagedComponent_1.ManagedComponent(this.behaviorPackBlockTypeDef.components, id, comp);
            }
        }
        return this._managed[id];
    }
    notifyComponentUpdated(id) {
        const component = this.getComponent(id);
        if (component === undefined) {
            Log_1.default.unexpectedUndefined("BTNCU");
        }
        else {
            this._onComponentChanged.dispatch(this, component);
        }
    }
    getAllComponents() {
        return this.getComponents();
    }
    getComponents() {
        const componentSet = [];
        if (this.behaviorPackBlockTypeDef !== undefined) {
            for (const componentName in this.behaviorPackBlockTypeDef.components) {
                const component = this.getComponent(componentName);
                if (component !== undefined) {
                    componentSet.push(component);
                }
            }
        }
        return componentSet;
    }
    addComponent(id, componentOrData) {
        this._ensureBehaviorPackDataInitialized();
        const bpData = this.behaviorPackBlockTypeDef;
        const mc = componentOrData instanceof ManagedComponent_1.ManagedComponent
            ? componentOrData
            : new ManagedComponent_1.ManagedComponent(bpData.components, id, componentOrData);
        bpData.components[id] = mc.getData();
        this._managed[id] = mc;
        this._onComponentAdded.dispatch(this, mc);
        return mc;
    }
    removeComponent(id) {
        if (this.behaviorPackBlockTypeDef === undefined) {
            return;
        }
        const newBehaviorPacks = {};
        const newComponents = {};
        for (const name in this.behaviorPackBlockTypeDef.components) {
            if (name !== id) {
                const component = this.behaviorPackBlockTypeDef.components[name];
                newBehaviorPacks[name] = component;
            }
        }
        for (const name in this._managed) {
            if (name !== id) {
                newComponents[name] = this._managed[name];
            }
        }
        this.behaviorPackBlockTypeDef.components = newBehaviorPacks;
        this._managed = newComponents;
    }
    _ensureBehaviorPackDataInitialized() {
        if (this.behaviorPackBlockTypeDef === undefined) {
            this.behaviorPackBlockTypeDef = {
                description: {
                    identifier: "unknown",
                },
                components: {},
                events: {},
            };
        }
    }
    persist() {
        if (this._behaviorPackFile === undefined) {
            return;
        }
        Log_1.default.assert(this._behaviorPackData !== null, "BTP");
        if (this._behaviorPackData) {
            const bpString = JSON.stringify(this._behaviorPackData, null, 2);
            this._behaviorPackFile.setContent(bpString);
        }
    }
    async load() {
        if (this._behaviorPackFile === undefined || this._isLoaded) {
            return;
        }
        if (!this._behaviorPackFile.isContentLoaded) {
            await this._behaviorPackFile.loadContent();
        }
        if (!this._behaviorPackFile.content || this._behaviorPackFile.content instanceof Uint8Array) {
            return;
        }
        let data = {};
        let result = StorageUtilities_1.default.getJsonObject(this._behaviorPackFile);
        if (result) {
            data = result;
        }
        this._behaviorPackData = data;
        const block = data["minecraft:block"];
        if (block.description) {
            this.id = block.description.identifier;
        }
        this.behaviorPackBlockTypeDef = block;
        this._onLoaded.dispatch(this, this);
        this._isLoaded = true;
    }
}
exports.default = BlockType;

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