"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
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());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SiteAssetsManager = void 0;
const fs_extra_1 = __importDefault(require("fs-extra"));
const ignore_1 = __importDefault(require("ignore"));
const path_1 = __importDefault(require("path"));
const walk_sync_1 = __importDefault(require("walk-sync"));
const delay_1 = require("../utils/delay");
const logger = __importStar(require("../utils/logger"));
const constants_1 = require("./constants");
function getBootswatchThemePath(theme) {
    return require.resolve(`bootswatch/dist/${theme}/bootstrap.min.css`);
}
const SUPPORTED_THEMES_PATHS = {
    'bootswatch-cerulean': getBootswatchThemePath('cerulean'),
    'bootswatch-cosmo': getBootswatchThemePath('cosmo'),
    'bootswatch-flatly': getBootswatchThemePath('flatly'),
    'bootswatch-journal': getBootswatchThemePath('journal'),
    'bootswatch-litera': getBootswatchThemePath('litera'),
    'bootswatch-lumen': getBootswatchThemePath('lumen'),
    'bootswatch-lux': getBootswatchThemePath('lux'),
    'bootswatch-materia': getBootswatchThemePath('materia'),
    'bootswatch-minty': getBootswatchThemePath('minty'),
    'bootswatch-pulse': getBootswatchThemePath('pulse'),
    'bootswatch-sandstone': getBootswatchThemePath('sandstone'),
    'bootswatch-simplex': getBootswatchThemePath('simplex'),
    'bootswatch-sketchy': getBootswatchThemePath('sketchy'),
    'bootswatch-spacelab': getBootswatchThemePath('spacelab'),
    'bootswatch-united': getBootswatchThemePath('united'),
    'bootswatch-yeti': getBootswatchThemePath('yeti'),
    'bootswatch-zephyr': getBootswatchThemePath('zephyr'),
};
/**
 * Manages site assets such as CSS, JS, fonts, and images.
 * Handles copying, building, and removing assets, as well as handling style reloads.
 */
class SiteAssetsManager {
    constructor(rootPath, outputPath) {
        /**
         * Build/copy assets that are specified in filePaths
         * @param filePaths a single path or an array of paths corresponding to the assets to build
        */
        this.buildAsset = (0, delay_1.delay)(this._buildMultipleAssets.bind(this), 1000);
        /**
         * Remove assets that are specified in filePaths
         * @param filePaths a single path or an array of paths corresponding to the assets to remove
         */
        this.removeAsset = (0, delay_1.delay)(this._removeMultipleAssets.bind(this), 1000);
        this.rootPath = rootPath;
        this.outputPath = outputPath;
        this.siteAssetsDestPath = path_1.default.join(outputPath, constants_1.TEMPLATE_SITE_ASSET_FOLDER_NAME);
    }
    listAssets(fileIgnore) {
        const files = (0, walk_sync_1.default)(this.rootPath, { directories: false });
        return fileIgnore.filter(files);
    }
    _buildMultipleAssets(filePaths) {
        return __awaiter(this, void 0, void 0, function* () {
            const filePathArray = Array.isArray(filePaths) ? filePaths : [filePaths];
            const uniquePaths = constants_1._.uniq(filePathArray);
            const fileIgnore = (0, ignore_1.default)().add(this.siteConfig.ignore);
            const fileRelativePaths = uniquePaths.map(filePath => path_1.default.relative(this.rootPath, filePath));
            const copyAssets = fileIgnore.filter(fileRelativePaths)
                .map(asset => fs_extra_1.default.copy(path_1.default.join(this.rootPath, asset), path_1.default.join(this.outputPath, asset)));
            yield Promise.all(copyAssets);
            logger.info('Assets built');
        });
    }
    _removeMultipleAssets(filePaths) {
        return __awaiter(this, void 0, void 0, function* () {
            const filePathArray = Array.isArray(filePaths) ? filePaths : [filePaths];
            const uniquePaths = constants_1._.uniq(filePathArray);
            const fileRelativePaths = uniquePaths.map(filePath => path_1.default.relative(this.rootPath, filePath));
            const filesToRemove = fileRelativePaths.map(fileRelativePath => path_1.default.join(this.outputPath, fileRelativePath));
            const removeFiles = filesToRemove.map(asset => fs_extra_1.default.remove(asset));
            if (removeFiles.length !== 0) {
                yield Promise.all(removeFiles);
                logger.debug('Assets removed');
            }
        });
    }
    buildAssets() {
        return __awaiter(this, void 0, void 0, function* () {
            logger.info('Building assets...');
            const outputFolder = path_1.default.relative(this.rootPath, this.outputPath);
            const fileIgnore = (0, ignore_1.default)().add([...this.siteConfig.ignore, outputFolder]);
            // Scan and copy assets (excluding ignore files).
            const listOfAssets = this.listAssets(fileIgnore);
            const assetsToCopy = listOfAssets.map(asset => fs_extra_1.default.copy(path_1.default.join(this.rootPath, asset), path_1.default.join(this.outputPath, asset)));
            yield Promise.all(assetsToCopy);
            logger.info('Assets built');
        });
    }
    /**
     * Handles the reloading of ignore attributes
     */
    handleIgnoreReload(oldIgnore) {
        return __awaiter(this, void 0, void 0, function* () {
            const assetsToRemove = constants_1._.difference(this.siteConfig.ignore, oldIgnore);
            if (!constants_1._.isEqual(oldIgnore, this.siteConfig.ignore)) {
                yield this._removeMultipleAssets(assetsToRemove);
                yield this.buildAssets();
            }
        });
    }
    /**
     * Handles the reloading of the style attribute if it has been modified
     */
    handleStyleReload(oldStyle) {
        return __awaiter(this, void 0, void 0, function* () {
            if (!constants_1._.isEqual(oldStyle.bootstrapTheme, this.siteConfig.style.bootstrapTheme)) {
                yield this.copyBootstrapTheme(true);
                logger.info('Updated bootstrap theme');
            }
        });
    }
    /**
     * Copies Font Awesome assets to the assets folder
     */
    copyFontAwesomeAsset() {
        return __awaiter(this, void 0, void 0, function* () {
            const faRootSrcPath = path_1.default.dirname(require.resolve('@fortawesome/fontawesome-free/package.json'));
            const faCssSrcPath = path_1.default.join(faRootSrcPath, 'css', 'all.min.css');
            const faCssDestPath = path_1.default.join(this.siteAssetsDestPath, 'fontawesome', 'css', 'all.min.css');
            const faFontsSrcPath = path_1.default.join(faRootSrcPath, 'webfonts');
            const faFontsDestPath = path_1.default.join(this.siteAssetsDestPath, 'fontawesome', 'webfonts');
            yield fs_extra_1.default.copy(faCssSrcPath, faCssDestPath);
            yield fs_extra_1.default.copy(faFontsSrcPath, faFontsDestPath);
        });
    }
    /**
     * Copies Octicon assets to the assets folder
     */
    copyOcticonsAsset() {
        const octiconsCssSrcPath = require.resolve('@primer/octicons/build/build.css');
        const octiconsCssDestPath = path_1.default.join(this.siteAssetsDestPath, 'css', 'octicons.css');
        return fs_extra_1.default.copy(octiconsCssSrcPath, octiconsCssDestPath);
    }
    /**
     * Copies Google Material Icons assets to the assets folder
     */
    copyMaterialIconsAsset() {
        const materialIconsRootSrcPath = path_1.default.dirname(require.resolve('material-icons/package.json'));
        const materialIconsCssAndFontsSrcPath = path_1.default.join(materialIconsRootSrcPath, 'iconfont');
        const materialIconsCssAndFontsDestPath = path_1.default.join(this.siteAssetsDestPath, 'material-icons');
        return fs_extra_1.default.copy(materialIconsCssAndFontsSrcPath, materialIconsCssAndFontsDestPath);
    }
    /**
     * Copies core-web bundles and external assets to the assets output folder
     */
    copyCoreWebAsset() {
        const coreWebRootPath = path_1.default.dirname(require.resolve('@markbind/core-web/package.json'));
        const coreWebAssetPath = path_1.default.join(coreWebRootPath, 'asset');
        fs_extra_1.default.copySync(coreWebAssetPath, this.siteAssetsDestPath);
        const dirsToCopy = ['fonts'];
        const filesToCopy = [
            'js/markbind.min.js',
            'css/markbind.min.css',
        ];
        const copyAllFiles = filesToCopy.map((file) => {
            const srcPath = path_1.default.join(coreWebRootPath, 'dist', file);
            const destPath = path_1.default.join(this.siteAssetsDestPath, file);
            return fs_extra_1.default.copy(srcPath, destPath);
        });
        const copyFontsDir = dirsToCopy.map((dir) => {
            const srcPath = path_1.default.join(coreWebRootPath, 'dist', dir);
            const destPath = path_1.default.join(this.siteAssetsDestPath, 'css', dir);
            return fs_extra_1.default.copy(srcPath, destPath);
        });
        return Promise.all([...copyAllFiles, ...copyFontsDir]);
    }
    copyBootstrapIconsAsset() {
        const bootstrapIconsCssSrcPath = require.resolve('bootstrap-icons/font/bootstrap-icons.css');
        const bootstrapIconsFontsSrcPath = path_1.default.dirname(bootstrapIconsCssSrcPath);
        const bootstrapIconsFontsDestPath = path_1.default.join(this.siteAssetsDestPath, 'bootstrap-icons', 'font');
        return fs_extra_1.default.copy(bootstrapIconsFontsSrcPath, bootstrapIconsFontsDestPath);
    }
    /**
     * Copies bootstrapTheme to the assets folder if a valid bootstrapTheme is specified
     * @param isRebuild only true if it is a rebuild
     */
    copyBootstrapTheme(isRebuild) {
        const { bootstrapTheme } = this.siteConfig.style;
        if ((!isRebuild && !bootstrapTheme)
            || (bootstrapTheme && !constants_1._.has(SUPPORTED_THEMES_PATHS, bootstrapTheme))) {
            return Promise.resolve();
        }
        const themeSrcPath = !bootstrapTheme
            ? require.resolve('@markbind/core-web/asset/css/bootstrap.min.css')
            : SUPPORTED_THEMES_PATHS[bootstrapTheme];
        const themeDestPath = path_1.default.join(this.siteAssetsDestPath, 'css', 'bootstrap.min.css');
        return fs_extra_1.default.copy(themeSrcPath, themeDestPath);
    }
}
exports.SiteAssetsManager = SiteAssetsManager;
//# sourceMappingURL=SiteAssetsManager.js.map