"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const chalk = require("chalk");
const Handlebars = require("handlebars");
const consolidate_1 = require("consolidate");
const path = require("path");
const ask_1 = require("./ask");
const filter_1 = require("./filter");
const logger = require("./logger");
const options_1 = require("./options");
const slug = require("slug");
const Metalsmith = require("metalsmith");
const renderTemplateFiles_1 = require("./renderTemplateFiles");
const { render } = consolidate_1.handlebars;
Handlebars.registerHelper('if_eq', function (a, b, opts) {
    return a === b ? opts.fn(this) : opts.inverse(this);
});
Handlebars.registerHelper('unless_eq', function (a, b, opts) {
    return a === b ? opts.inverse(this) : opts.fn(this);
});
function generate(src, dest, options, metadata) {
    const projectName = path.basename(dest);
    const opts = (0, options_1.default)(projectName, options.id, src, metadata);
    const helpers = { chalk, logger };
    const metalsmith = Metalsmith(path.join(src, 'template'));
    const data = Object.assign(metalsmith.metadata(metadata), {
        destDirName: projectName,
        noEscape: true,
        inPlace: dest === process.cwd(),
    });
    opts.helpers &&
        Object.keys(opts.helpers).map((key) => {
            Handlebars.registerHelper(key, opts.helpers[key]);
        });
    if (opts.metalsmith && typeof opts.metalsmith.before === 'function') {
        opts.metalsmith.before(metalsmith, opts, helpers);
    }
    metalsmith
        .use(askQuestions(opts.prompts, options))
        .use(setPackageName(options))
        .use(setPackageId(options))
        .use(filterFiles(opts.filters))
        .use((0, renderTemplateFiles_1.renderTemplateFiles)(opts.skipInterpolation));
    if (typeof opts.metalsmith === 'function') {
        opts.metalsmith(metalsmith, opts, helpers);
    }
    else if (opts.metalsmith && typeof opts.metalsmith.after === 'function') {
        opts.metalsmith.after(metalsmith, opts, helpers);
    }
    return new Promise((resolve, reject) => {
        metalsmith
            .clean(false)
            .source('.')
            .destination(dest)
            .build((err, files) => {
            if (typeof opts.complete === 'function') {
                const helpers = { chalk, logger, files };
                opts.complete(data, helpers);
            }
            else {
                logMessage(opts.completeMessage, data);
            }
            if (err) {
                return reject(err);
            }
            return resolve(data);
        });
    });
}
exports.default = generate;
function setPackageName(options) {
    return (files, metalsmith, done) => {
        const metadata = metalsmith.metadata();
        metadata.packageName = slug(metadata.name);
        done();
    };
}
function setPackageId(options) {
    return (files, metalsmith, done) => {
        const metadata = metalsmith.metadata();
        metadata.id = options.id;
        done();
    };
}
function askQuestions(prompts, options) {
    return (files, metalsmith, done) => {
        (0, ask_1.default)(prompts, options, metalsmith.metadata(), done);
    };
}
function filterFiles(filters) {
    return (files, metalsmith, done) => {
        (0, filter_1.default)(files, filters, metalsmith.metadata(), done);
    };
}
function logMessage(message, data) {
    if (!message)
        return;
    render(message, data, (err, res) => {
        if (err) {
            console.error(`\n   Error when rendering template complete message: ${err.message.trim()}`);
        }
        else {
            console.log(`\n${res
                .split(/\r?\n/g)
                .map((line) => `   ${line}`)
                .join('\n')}`);
        }
    });
}
//# sourceMappingURL=index.js.map