"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
const ProjectContent_1 = require("./ProjectContent");
const IProjectData_1 = require("./IProjectData");
const IProjectItemData_1 = require("./IProjectItemData");
const StorageUtilities_1 = require("./../storage/StorageUtilities");
const ZipStorage_1 = require("../storage/ZipStorage");
const ProjectItemUtilities_1 = require("./ProjectItemUtilities");
const ProjectAutogeneration_1 = require("./ProjectAutogeneration");
class ProjectItemManager {
    static async _getDefaultBehaviorPackPath(project) {
        const bpFolder = await project.ensureDefaultBehaviorPackFolder();
        if (project.projectFolder === null) {
            return undefined;
        }
        const defaultPath = bpFolder.getFolderRelativePath(project.projectFolder);
        return defaultPath;
    }
    static async _getDefaultBehaviorPackFolderPath(project, name) {
        const bpFolder = await project.ensureDefaultBehaviorPackFolder();
        if (project.projectFolder === null) {
            return undefined;
        }
        const subfolder = bpFolder.ensureFolder(name);
        await subfolder.ensureExists();
        const defaultPath = subfolder.getFolderRelativePath(project.projectFolder);
        return defaultPath;
    }
    static async _getDefaultScriptsFolderPath(project) {
        const scriptsFolder = await project.ensureMainScriptsFolder();
        if (project.projectFolder === null) {
            return undefined;
        }
        const defaultPath = scriptsFolder.getFolderRelativePath(project.projectFolder);
        return defaultPath;
    }
    static async createNewItem(project, itemSeed) {
        if (itemSeed.name === "" || itemSeed.name === undefined) {
            itemSeed.name = ProjectItemUtilities_1.default.getNewItemName(itemSeed.itemType);
        }
        if (itemSeed.itemType) {
            switch (itemSeed.itemType) {
                case IProjectItemData_1.ProjectItemType.js:
                case IProjectItemData_1.ProjectItemType.ts:
                    return ProjectItemManager.createNewScript(project, itemSeed.itemType, itemSeed.name, itemSeed.folder);
                case IProjectItemData_1.ProjectItemType.dataForm:
                    return ProjectItemManager.createNewForm(project, itemSeed.name, itemSeed.folder);
                case IProjectItemData_1.ProjectItemType.spawnRuleBehavior:
                    return ProjectItemManager.createNewSpawnRule(project, itemSeed.name, itemSeed.folder);
            }
        }
        return undefined;
    }
    static async createNewScript(project, itemType, name, folder) {
        let defaultPath = undefined;
        if (folder && project.projectFolder) {
            defaultPath = folder.getFolderRelativePath(project.projectFolder);
        }
        else {
            defaultPath = await ProjectItemManager._getDefaultScriptsFolderPath(project);
        }
        if (defaultPath === undefined) {
            return;
        }
        const candidateFilePath = await ProjectItemManager._generateFileNameForNewItem(project, defaultPath, name, itemType === IProjectItemData_1.ProjectItemType.js ? "js" : "ts");
        if (candidateFilePath === undefined) {
            return;
        }
        const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), itemType === IProjectItemData_1.ProjectItemType.js ? IProjectItemData_1.ProjectItemType.js : IProjectItemData_1.ProjectItemType.ts, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
        const file = await pi.ensureFileStorage();
        if (file !== null) {
            const baseName = StorageUtilities_1.default.getBaseFromName(file.name);
            if (project.preferredScriptLanguage === IProjectData_1.ProjectScriptLanguage.typeScript) {
                file.setContent(ProjectContent_1.default.getEmptyTypeScript(project.name, baseName));
            }
            else {
                file.setContent(ProjectContent_1.default.getEmptyJavaScript(project.name, baseName));
            }
        }
        await ProjectAutogeneration_1.default.updateProjectAutogeneration(project);
        await project.save();
        return pi;
    }
    static async _generateFolderNameForNewItem(project, basePath, baseName) {
        if (project.projectFolder === null) {
            return undefined;
        }
        let index = 0;
        let candidateFolderPath = "";
        let finalPathPrefix = "";
        const projectFolder = project.projectFolder;
        let candidateFolder = null;
        let hash = basePath.indexOf("#");
        let targetFolder = projectFolder;
        while (hash > 0) {
            // dig into container files if needed.
            let containerFilePath = basePath.substring(0, hash);
            basePath = basePath.substring(hash + 1);
            hash = basePath.indexOf("#");
            if (containerFilePath.startsWith(targetFolder.fullPath)) {
                containerFilePath = containerFilePath.substring(targetFolder.fullPath.length);
            }
            finalPathPrefix += containerFilePath + "#";
            const containerFile = await targetFolder.getFileFromRelativePath(containerFilePath);
            if (!containerFile) {
                return undefined;
            }
            const extension = containerFile.type;
            if (extension !== "zip" && extension !== "mcworld" && extension !== "mctemplate") {
                return undefined;
            }
            if (!containerFile.fileContainerStorage) {
                const zipStorage = new ZipStorage_1.default();
                await containerFile.loadContent();
                if (!containerFile.content || !(containerFile.content instanceof Uint8Array)) {
                    return undefined;
                }
                await zipStorage.loadFromUint8Array(containerFile.content, containerFile.name);
                containerFile.fileContainerStorage = zipStorage;
                containerFile.fileContainerStorage.storagePath = containerFilePath + "#";
            }
            targetFolder = containerFile.fileContainerStorage.rootFolder;
        }
        await targetFolder.ensureFolderFromRelativePath(basePath);
        await targetFolder.ensureExists();
        // find a folder name not in use
        do {
            index++;
            candidateFolderPath = basePath + baseName + index;
            candidateFolder = await targetFolder.getFolderFromRelativePath(candidateFolderPath);
        } while (candidateFolder !== null && candidateFolder !== undefined);
        return finalPathPrefix + candidateFolderPath;
    }
    static async _generateFileNameForNewItem(project, basePath, baseName, extension) {
        if (project.projectFolder === null) {
            return undefined;
        }
        let index = 0;
        let candidateFilePath = "";
        let finalPathPrefix = "";
        const projectFolder = project.projectFolder;
        let candidateFile = null;
        let hash = basePath.indexOf("#");
        let targetFolder = projectFolder;
        while (hash > 0) {
            // dig into container files if needed.
            let containerFilePath = basePath.substring(0, hash);
            basePath = basePath.substring(hash + 1);
            hash = basePath.indexOf("#");
            if (containerFilePath.startsWith(targetFolder.fullPath)) {
                containerFilePath = containerFilePath.substring(targetFolder.fullPath.length);
            }
            finalPathPrefix += containerFilePath + "#";
            const containerFile = await targetFolder.getFileFromRelativePath(containerFilePath);
            if (!containerFile) {
                return undefined;
            }
            const extension = containerFile.type;
            if (extension !== "zip" && extension !== "mcworld" && extension !== "mctemplate") {
                return undefined;
            }
            if (!containerFile.fileContainerStorage) {
                const zipStorage = new ZipStorage_1.default();
                await containerFile.loadContent();
                if (!containerFile.content || !(containerFile.content instanceof Uint8Array)) {
                    return undefined;
                }
                await zipStorage.loadFromUint8Array(containerFile.content);
                containerFile.fileContainerStorage = zipStorage;
                containerFile.fileContainerStorage.storagePath = containerFilePath + "#";
            }
            targetFolder = containerFile.fileContainerStorage.rootFolder;
        }
        await targetFolder.ensureFolderFromRelativePath(basePath);
        await targetFolder.ensureExists();
        candidateFilePath = basePath + baseName + "." + extension;
        candidateFile = await targetFolder.getFileFromRelativePath(candidateFilePath);
        if (candidateFile) {
            // find a filename not in use
            do {
                index++;
                candidateFilePath = basePath + baseName + index + "." + extension;
                candidateFile = await targetFolder.getFileFromRelativePath(candidateFilePath);
            } while (candidateFile !== null && candidateFile !== undefined);
        }
        return finalPathPrefix + candidateFilePath;
    }
    static async createNewGameTestScript(project) {
        const defaultPath = await ProjectItemManager._getDefaultBehaviorPackFolderPath(project, "scripts");
        if (defaultPath === undefined) {
            return;
        }
        const candidateFilePath = await ProjectItemManager._generateFileNameForNewItem(project, defaultPath, "test", "js");
        if (candidateFilePath === undefined) {
            return;
        }
        const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), IProjectItemData_1.ProjectItemType.testJs, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
        const file = await pi.ensureFileStorage();
        if (file !== null) {
            const baseName = StorageUtilities_1.default.getBaseFromName(file.name);
            if (project.preferredScriptLanguage === IProjectData_1.ProjectScriptLanguage.typeScript) {
                const tsFile = file.parentFolder.ensureFile(baseName + ".ts");
                if (tsFile !== null) {
                    const content = ProjectContent_1.default.getEmptyTestTypeScript(project.name, baseName);
                    tsFile.setContent(content);
                }
            }
            const content = ProjectContent_1.default.getEmptyTestJavaScript(project.name, baseName);
            file.setContent(content);
        }
        await project.save();
    }
    static async createNewFunction(project) {
        const defaultPath = await this._getDefaultBehaviorPackFolderPath(project, "functions");
        if (defaultPath === undefined) {
            return;
        }
        const candidateFilePath = await ProjectItemManager._generateFileNameForNewItem(project, defaultPath, "action", "mcfunction");
        if (candidateFilePath === undefined) {
            return;
        }
        const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), IProjectItemData_1.ProjectItemType.MCFunction, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
        const file = await pi.ensureFileStorage();
        if (file !== null) {
            const content = "say hello";
            file.setContent(content);
        }
        await project.save();
    }
    static async createNewStructure(project) {
        const defaultPath = await ProjectItemManager._getDefaultBehaviorPackFolderPath(project, "structures");
        if (defaultPath === undefined) {
            return;
        }
        const candidateFilePath = await ProjectItemManager._generateFileNameForNewItem(project, defaultPath, "structure", "mcstructure");
        if (candidateFilePath === undefined) {
            return;
        }
        const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), IProjectItemData_1.ProjectItemType.structure, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
        const file = await pi.ensureFileStorage();
        if (file !== null) {
            const structureBytes = ProjectContent_1.default.generateDefaultStructure();
            if (structureBytes !== undefined) {
                file.setContent(structureBytes);
            }
        }
        await project.save();
    }
    static async createNewActionSet(project) {
        const defaultPath = await this._getDefaultBehaviorPackFolderPath(project, "actions");
        if (defaultPath === undefined) {
            return;
        }
        const candidateFilePath = await ProjectItemManager._generateFileNameForNewItem(project, defaultPath, "actionset", "json");
        if (candidateFilePath === undefined) {
            return;
        }
        const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), IProjectItemData_1.ProjectItemType.actionSet, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
        const file = await pi.ensureFileStorage();
        if (file !== null) {
            const baseName = StorageUtilities_1.default.getBaseFromName(file.name);
            const content = ProjectContent_1.default.getEmptyActionSet(project.name, baseName);
            file.setContent(content);
        }
        await ProjectAutogeneration_1.default.updateProjectAutogeneration(project);
    }
    static async createNewDocumentedType(project) {
        const defaultPath = await this._getDefaultBehaviorPackFolderPath(project, "docs");
        if (defaultPath === undefined) {
            return;
        }
        const candidateFolderPath = await ProjectItemManager._generateFolderNameForNewItem(project, defaultPath, "type");
        if (candidateFolderPath === undefined) {
            return;
        }
        const pi = project.ensureItemByProjectPath(candidateFolderPath, IProjectItemData_1.ProjectItemStorageType.folder, candidateFolderPath, IProjectItemData_1.ProjectItemType.documentedTypeFolder, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
        await pi.ensureFolderStorage();
        await ProjectAutogeneration_1.default.updateProjectAutogeneration(project);
        await project.save();
    }
    static getExistingPath(project, itemType) {
        if (!project.projectFolder) {
            return undefined;
        }
        for (const item of project.items) {
            if (item.itemType === itemType && item.file) {
                return item.file.parentFolder.getFolderRelativePath(project.projectFolder);
            }
        }
        return undefined;
    }
    static async createNewForm(project, name, folder) {
        let path = undefined;
        if (!project.projectFolder) {
            return undefined;
        }
        if (folder) {
            path = folder.getFolderRelativePath(project.projectFolder);
        }
        else {
            path = ProjectItemManager.getExistingPath(project, IProjectItemData_1.ProjectItemType.dataForm);
            if (path === undefined) {
                path = await this._getDefaultBehaviorPackFolderPath(project, "forms");
                if (path === undefined) {
                    return undefined;
                }
            }
        }
        if (!path) {
            return undefined;
        }
        if (!name) {
            name = "form";
        }
        const candidateFilePath = await ProjectItemManager._generateFileNameForNewItem(project, path, name, "form.json");
        if (candidateFilePath === undefined) {
            return undefined;
        }
        const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), IProjectItemData_1.ProjectItemType.dataForm, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
        const file = await pi.ensureFileStorage();
        if (file !== null) {
            const content = "{}";
            file.setContent(content);
        }
        await ProjectAutogeneration_1.default.updateProjectAutogeneration(project);
        await project.save();
        return pi;
    }
    static async createNewSpawnRule(project, name, folder) {
        let path = undefined;
        if (!project.projectFolder) {
            return undefined;
        }
        if (folder) {
            path = folder.getFolderRelativePath(project.projectFolder);
        }
        else {
            path = ProjectItemManager.getExistingPath(project, IProjectItemData_1.ProjectItemType.spawnRuleBehavior);
            if (path === undefined) {
                path = await this._getDefaultBehaviorPackFolderPath(project, "spawn_rules");
                if (path === undefined) {
                    return undefined;
                }
            }
        }
        if (!path) {
            return undefined;
        }
        if (!name) {
            name = "spawn_rule";
        }
        const candidateFilePath = await ProjectItemManager._generateFileNameForNewItem(project, path, name, "json");
        if (candidateFilePath === undefined) {
            return undefined;
        }
        const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), IProjectItemData_1.ProjectItemType.spawnRuleBehavior, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
        const file = await pi.ensureFileStorage();
        if (file !== null) {
            const content = "{}";
            file.setContent(content);
        }
        await ProjectAutogeneration_1.default.updateProjectAutogeneration(project);
        await project.save();
        return pi;
    }
    static async createNewWorldTest(project, name, folder) {
        let path = undefined;
        if (!project.projectFolder) {
            return;
        }
        if (folder) {
            path = folder.getFolderRelativePath(project.projectFolder);
        }
        else {
            path = ProjectItemManager.getExistingPath(project, IProjectItemData_1.ProjectItemType.dataForm);
            if (path === undefined) {
                path = await this._getDefaultBehaviorPackFolderPath(project, "forms");
                if (path === undefined) {
                    return;
                }
            }
        }
        if (!path) {
            return;
        }
        if (!name) {
            name = "form";
        }
        const candidateFilePath = await ProjectItemManager._generateFileNameForNewItem(project, path + "tests/", "worldtest", "json");
        if (candidateFilePath === undefined) {
            return;
        }
        const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), IProjectItemData_1.ProjectItemType.worldTest, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
        const file = await pi.ensureFileStorage();
        if (file !== null) {
            const baseName = StorageUtilities_1.default.getBaseFromName(file.name);
            const content = ProjectContent_1.default.getEmptyWorldTest(project.name, baseName);
            file.setContent(content);
        }
        await ProjectAutogeneration_1.default.updateProjectAutogeneration(project);
        await project.save();
    }
}
exports.default = ProjectItemManager;

//# sourceMappingURL=../maps/app/ProjectItemManager.js.map
