"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const settings_1 = require("@ewizardjs/settings");
const system_settings_1 = require("@ewizardjs/system-settings");
const AdmZip = require("adm-zip");
const fs_extra_1 = require("fs-extra");
const globby = require("globby");
const ramda_1 = require("ramda");
const upath_1 = require("upath");
const filesPattern_1 = require("./filesPattern");
const utils_1 = require("./utils");
const SETTINGS_JSON = 'settings.json';
class Archiver {
    constructor(presentationPath, options) {
        this.presentationPath = presentationPath;
        this.options = options;
    }
    zip() {
        return __awaiter(this, void 0, void 0, function* () {
            const files = yield this.collectFilesToArchive();
            return this.archive(files);
        });
    }
    collectFilesToArchive() {
        return __awaiter(this, void 0, void 0, function* () {
            const [requiredFiles, files] = yield Promise.all([
                globby(filesPattern_1.REQUIRED_FILES_PATTERNS, { cwd: this.presentationPath, dot: true }),
                globby(yield this.getFilePatterns(), { cwd: this.presentationPath, dot: true }),
            ]);
            return ramda_1.uniq(requiredFiles.concat(files));
        });
    }
    archive(filesPaths) {
        return __awaiter(this, void 0, void 0, function* () {
            const zip = new AdmZip();
            const archiveName = yield this.getArchiveName();
            const zipPath = this.getZipPath(archiveName);
            yield zip.addLocalFolderPromise(this.presentationPath, {
                filter: (filename) => {
                    return filesPaths.includes(filename);
                },
            });
            const settingsJson = yield this.getSettingsJson();
            const updatedSettingsJson = getUpdatedSettingsJson(settingsJson, this.options);
            const prettySettingsJsonObject = JSON.stringify(updatedSettingsJson, null, 2);
            zip.addFile(SETTINGS_JSON, Buffer.from(prettySettingsJsonObject));
            return zip.writeZipPromise(zipPath);
        });
    }
    getArchiveName() {
        return __awaiter(this, void 0, void 0, function* () {
            const settingsJSON = yield this.getSettingsJson();
            const optionsName = this.options.name
                ? removeUnallowedFileNameSymbols(this.options.name)
                : this.options.name;
            const settingsName = removeUnallowedFileNameSymbols(settingsJSON.name);
            const directoryName = upath_1.basename(this.presentationPath);
            return optionsName ? optionsName : settingsName ? settingsName : directoryName;
        });
    }
    getZipPath(archiveName) {
        const path = this.options.archiveDest || this.options.rootPath;
        return upath_1.join(path, `${archiveName}.zip`);
    }
    getFilePatterns(ignoredFiles = []) {
        return __awaiter(this, void 0, void 0, function* () {
            const settings = yield system_settings_1.get(this.options.rootPath);
            const ignoreLayoutsFolder = `./${settings.path.layouts}`;
            settings.archive.ignore.push(...ignoredFiles, ignoreLayoutsFolder);
            return this.getMergedPatterns(settings === null || settings === void 0 ? void 0 : settings.archive, ignoreLayoutsFolder);
        });
    }
    getMergedPatterns(archiveSettings, ignoreLayoutsFolder) {
        const mergedPatterns = ramda_1.clone(filesPattern_1.DEFAULT_FILES_PATTERN);
        const { patterns, ignore } = archiveSettings !== null && archiveSettings !== void 0 ? archiveSettings : {};
        if (patterns) {
            mergedPatterns.push(...patterns);
        }
        else if (ignore) {
            mergedPatterns.push(...utils_1.getRevertedIgnorePatterns(ignore));
        }
        mergedPatterns.push(`!${ignoreLayoutsFolder}`);
        return mergedPatterns;
    }
    getSettingsJson() {
        return __awaiter(this, void 0, void 0, function* () {
            const settingsPath = (yield system_settings_1.get(this.presentationPath)).path.settings;
            return fs_extra_1.readJSON(upath_1.join(this.presentationPath, settingsPath));
        });
    }
}
exports.default = Archiver;
function getUpdatedSettingsJson(settingsJsonContent, options) {
    const updatedSettingsTarget = updateSettingsTarget(settingsJsonContent, options);
    const updatedSettingsTheme = updateSettingsTheme(updatedSettingsTarget, options);
    return updateSettingsScheme(updatedSettingsTheme, options);
}
function updateSettingsTarget(settingsFile, options) {
    const updatedSettings = ramda_1.clone(settingsFile);
    if (options.target) {
        updatedSettings.targetCLM = {
            name: getClmName(options.target),
            code: options.target,
        };
    }
    return updatedSettings;
}
function getClmName(clm) {
    const targetCLMs = settings_1.TargetCLMs;
    return targetCLMs[clm] || clm;
}
function updateSettingsTheme(settingsFile, options) {
    let updatedSettings = ramda_1.clone(settingsFile);
    if (options.theme) {
        if (!isObject(updatedSettings.theme)) {
            updatedSettings.theme = {};
        }
        Object.assign(updatedSettings.theme, {
            current: options.theme,
        });
        if (isString(updatedSettings.scheme)) {
            updatedSettings = updateScheme(updatedSettings, updatedSettings.scheme);
        }
    }
    return updatedSettings;
}
function updateSettingsScheme(settingsFile, options) {
    let updatedSettings = ramda_1.clone(settingsFile);
    if (options.scheme) {
        if (isUndefined(updatedSettings.theme)) {
            updatedSettings.theme = {};
        }
        if (isString(updatedSettings.theme)) {
            updatedSettings.theme = {
                current: updatedSettings.theme,
            };
        }
        updatedSettings = updateScheme(updatedSettings, options.scheme);
    }
    return updatedSettings;
}
function updateScheme(settings, newScheme) {
    const updatedSettings = ramda_1.clone(settings);
    Object.assign(updatedSettings.theme, {
        scheme: newScheme,
    });
    delete updatedSettings.scheme;
    return updatedSettings;
}
function removeUnallowedFileNameSymbols(filename) {
    return filename.replace(/\\|\/|:|\*|\?|"|<|>|\|/g, '');
}
function isObject(object) {
    return object instanceof Object && object.constructor === Object;
}
function isUndefined(object) {
    return typeof object === 'undefined';
}
function isString(object) {
    return typeof object === 'string' || object instanceof String;
}
//# sourceMappingURL=Archiver.js.map