"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
const ZipFile_1 = require("./ZipFile");
const ZipStorage_1 = require("./ZipStorage");
const StorageUtilities_1 = require("./StorageUtilities");
const FolderBase_1 = require("./FolderBase");
const Utilities_1 = require("../core/Utilities");
const Log_1 = require("../core/Log");
class ZipFolder extends FolderBase_1.default {
    _name;
    _parentPath;
    folders;
    files;
    _storage;
    _parentFolder;
    _jsz;
    get ensuredName() {
        if (this.name.length > 0) {
            return this.name;
        }
        if (this.storage.name) {
            let name = this.storage.name;
            const lastPeriod = name.lastIndexOf(".");
            if (lastPeriod > 0) {
                name = name.substring(0, lastPeriod);
            }
            return name;
        }
        return "folder";
    }
    get zip() {
        return this._jsz;
    }
    set zip(newZip) {
        this._jsz = newZip;
    }
    get storage() {
        return this._storage;
    }
    get parentFolder() {
        return this._parentFolder;
    }
    get name() {
        return this._name;
    }
    get fullPath() {
        if (!this.parentFolder) {
            return "/";
        }
        return StorageUtilities_1.default.ensureEndsWithDelimiter(this._parentPath) + this.name;
    }
    constructor(storage, jszipThisFolder, parentFolder, parentPath, folderName) {
        super();
        this._jsz = jszipThisFolder;
        this._storage = storage;
        this._parentFolder = parentFolder;
        this._parentPath = parentPath;
        this._name = folderName;
        this.folders = {};
        this.files = {};
    }
    async exists() {
        return true;
    }
    async ensureExists() {
        return true;
    }
    ensureFile(name) {
        const nameCanon = StorageUtilities_1.default.canonicalizeName(name);
        if (!Utilities_1.default.isUsableAsObjectKey(nameCanon)) {
            throw new Error();
        }
        let candFile = this.files[nameCanon];
        if (candFile == null) {
            const zipObject = this._jsz.file(name);
            candFile = new ZipFile_1.default(this, name, zipObject);
            this.files[nameCanon] = candFile;
        }
        return candFile;
    }
    async moveTo(newStorageRelativePath) {
        throw new Error("Not implemented.");
    }
    ensureFolder(name) {
        const nameCanon = StorageUtilities_1.default.canonicalizeName(name);
        if (!Utilities_1.default.isUsableAsObjectKey(nameCanon)) {
            throw new Error();
        }
        let candFolder = this.folders[nameCanon];
        if (!candFolder) {
            const zipFolder = this._jsz.folder(name);
            if (zipFolder == null) {
                throw new Error("unexpected inability to create a zip file folder");
            }
            candFolder = new ZipFolder(this._storage, zipFolder, this, this.fullPath, name);
            this.folders[nameCanon] = candFolder;
        }
        return candFolder;
    }
    async deleteFile(name) {
        throw new Error("Deletion of file not supported");
    }
    async deleteThisFolder() {
        throw new Error("Deletion of this folder " + this.fullPath + " is not supported.");
    }
    async deleteAllFolderContents() {
        throw new Error("Deletion of all folder contents at " + this.fullPath + " is not supported.");
    }
    async createFile(name) {
        return this.ensureFile(name);
    }
    async load(force) {
        if (this.lastLoadedOrSaved != null && !force) {
            return this.lastLoadedOrSaved;
        }
        this.updateLastLoadedOrSaved();
        this._jsz.forEach((relativePath, file) => {
            // some zip files use \ as a delimiter (??)
            relativePath = relativePath.replace(/\\/gi, ZipStorage_1.default.slashFolderDelimiter);
            const countDelim = Utilities_1.default.countChar(relativePath, ZipStorage_1.default.slashFolderDelimiter);
            if (countDelim === 0) {
                const nameCanon = StorageUtilities_1.default.canonicalizeName(relativePath);
                if (!Utilities_1.default.isUsableAsObjectKey(nameCanon)) {
                    throw new Error();
                }
                let candFile = this.files[nameCanon];
                if (candFile == null && StorageUtilities_1.default.isUsableFile(StorageUtilities_1.default.getLeafName(relativePath))) {
                    candFile = new ZipFile_1.default(this, relativePath, file);
                    this.files[nameCanon] = candFile;
                }
            }
            else if (countDelim >= 1) {
                let lastFolder = this;
                let subPath = relativePath;
                if (subPath.startsWith("/")) {
                    subPath = subPath.substring(1);
                }
                let nextDelim = subPath.indexOf(ZipStorage_1.default.slashFolderDelimiter);
                while (nextDelim > 0) {
                    lastFolder = lastFolder.ensureFolder(subPath.substring(0, nextDelim));
                    subPath = subPath.substring(nextDelim + 1);
                    nextDelim = subPath.indexOf(ZipStorage_1.default.slashFolderDelimiter);
                }
                if (subPath.length > 0 && file) {
                    Log_1.default.assert(!file.dir, "Unexpected non directory file.");
                    if (StorageUtilities_1.default.isUsableFile(StorageUtilities_1.default.getLeafName(subPath))) {
                        const zipFile = lastFolder.ensureFile(subPath);
                        zipFile.updateZipNativeFile(file);
                    }
                    else {
                        Log_1.default.message("Unexpected file type found in zip file: " + subPath);
                    }
                }
            }
        });
        return this.lastLoadedOrSaved;
    }
}
exports.default = ZipFolder;

//# sourceMappingURL=../maps/storage/ZipFolder.js.map
