"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.initialize = void 0;
const tslib_1 = require("tslib");
const fs_1 = tslib_1.__importDefault(require("fs"));
const path_1 = tslib_1.__importDefault(require("path"));
const util_1 = tslib_1.__importDefault(require("util"));
const ml_config_1 = require("@markuplint/ml-config");
const util_2 = require("../../util");
const prompt_1 = require("../prompt");
const install_module_1 = require("./install-module");
const writeFile = util_1.default.promisify(fs_1.default.writeFile);
const ruleCategories = {
    validation: {
        message: 'Are you going to conformance check according to HTML standard?',
    },
    a11y: {
        message: 'Are you going to do with accessibility better practices?',
    },
    'naming-convention': {
        message: 'Are you going to set the convention about naming?',
    },
    style: {
        message: 'Are you going to check for the code styles?',
    },
};
const defaultRules = {
    'attr-duplication': {
        category: 'validation',
        default: true,
    },
    'attr-value-quotes': {
        category: 'style',
        default: true,
    },
    'case-sensitive-attr-name': {
        category: 'style',
        default: true,
    },
    'case-sensitive-attr-value': {
        category: 'style',
        default: true,
    },
    'case-sensitive-tag-name': {
        category: 'style',
        default: true,
    },
    'character-reference': {
        category: 'style',
        default: true,
    },
    'class-naming': {
        category: 'naming-convention',
        default: false,
        recommendedValue: '/.+/',
    },
    'deprecated-attr': {
        category: 'validation',
        default: true,
    },
    'deprecated-element': {
        category: 'validation',
        default: true,
    },
    'disallowed-element': {
        category: 'validation',
        default: false,
    },
    doctype: {
        category: 'validation',
        default: true,
    },
    'end-tag': {
        category: 'style',
        default: true,
    },
    'id-duplication': {
        category: 'validation',
        default: true,
    },
    'ineffective-attr': {
        category: 'validation',
        default: true,
    },
    'invalid-attr': {
        category: 'validation',
        default: true,
    },
    'label-has-control': {
        category: 'a11y',
        default: false,
    },
    'landmark-roles': {
        category: 'a11y',
        default: true,
    },
    'no-boolean-attr-value': {
        category: 'style',
        default: true,
    },
    'no-default-value': {
        category: 'style',
        default: true,
    },
    'no-empty-palpable-content': {
        category: 'validation',
        default: false,
    },
    'no-hard-code-id': {
        category: 'style',
        default: true,
    },
    'no-refer-to-non-existent-id': {
        category: 'a11y',
        default: true,
    },
    'no-use-event-handler-attr': {
        category: 'style',
        default: true,
    },
    'permitted-contents': {
        category: 'validation',
        default: true,
    },
    'required-attr': {
        category: 'validation',
        default: true,
    },
    'required-element': {
        category: 'validation',
        default: true,
    },
    'required-h1': {
        category: 'a11y',
        default: true,
    },
    'use-list': {
        category: 'a11y',
        default: false,
    },
    'wai-aria': {
        category: 'a11y',
        default: true,
    },
};
const extRExp = {
    jsx: '\\.[jt]sx?$',
    vue: '\\.vue$',
    svelte: '\\.svelte$',
    astro: '\\.astro',
    pug: '\\.pug$',
    php: '\\.php$',
    erb: '\\.erb$',
    ejs: '\\.ejs$',
    mustache: '\\.(mustache|handlebars)$',
    nunjucks: '\\.nunjucks$',
    liquid: '\\.liquid$',
};
async function initialize() {
    let config = {};
    (0, util_2.write)((0, util_2.head)('Initialization'));
    util_2.write.break();
    const langs = await (0, prompt_1.multiSelect)({
        message: 'Which do you use template engines?',
        choices: [
            { name: 'React (JSX)', value: 'jsx' },
            { name: 'Vue', value: 'vue' },
            { name: 'Svelte', value: 'svelte' },
            { name: 'Astro', value: 'astro' },
            { name: 'Pug', value: 'pug' },
            { name: 'PHP', value: 'php' },
            { name: 'Smarty', value: 'smarty' },
            { name: 'eRuby', value: 'erb' },
            { name: 'EJS', value: 'ejs' },
            { name: 'Mustache/Handlebars', value: 'mustache' },
            { name: 'Nunjucks', value: 'nunjucks' },
            { name: 'liquid (Shopify)', value: 'liquid' },
        ],
    });
    const autoInstall = await (0, prompt_1.confirm)('May I install them automatically?');
    const customize = await (0, prompt_1.confirm)('Do you customize rules?');
    for (const lang of langs) {
        config.parser = config.parser || {};
        // @ts-ignore
        const ext = extRExp[lang];
        if (!ext) {
            continue;
        }
        config.parser[ext] = `@markuplint/${lang}-parser`;
        if (lang === 'vue') {
            config = (0, ml_config_1.mergeConfig)(config, {
                specs: {
                    '\\.vue$': '@markuplint/vue-spec',
                },
            });
        }
        if (lang === 'jsx') {
            config = (0, ml_config_1.mergeConfig)(config, {
                specs: {
                    '\\.[jt]sx?$': '@markuplint/react-spec',
                },
            });
        }
    }
    if (customize) {
        const ruleNames = Object.keys(defaultRules);
        const categories = Object.keys(ruleCategories);
        const res = await (0, prompt_1.confirmSequence)(categories.map(catName => {
            const cat = ruleCategories[catName];
            return {
                message: cat.message,
                name: catName,
            };
        }));
        for (const ruleName of ruleNames) {
            const rule = defaultRules[ruleName];
            if (!rule) {
                continue;
            }
            if (res[rule.category]) {
                if (!config.rules) {
                    config.rules = {};
                }
                config.rules[ruleName] = rule.recommendedValue || true;
            }
        }
    }
    else {
        const recommended = await (0, prompt_1.confirm)('Does it import the recommended config?');
        if (recommended) {
            config.extends = [...(config.extends || []), 'markuplint:recommended'];
        }
        else {
            config.rules = {};
            const ruleNames = Object.keys(defaultRules);
            for (const ruleName of ruleNames) {
                const rule = defaultRules[ruleName];
                config.rules[ruleName] = rule.default;
            }
        }
    }
    const filePath = path_1.default.resolve(process.cwd(), '.markuplintrc');
    await writeFile(filePath, JSON.stringify(config, null, 2), { encoding: 'utf-8' });
    (0, util_2.write)(`✨Created: ${filePath}`);
    if (autoInstall) {
        (0, util_2.write)('Install automatically');
        const modules = ['markuplint', ...langs.map(lang => `@markuplint/${lang}-parser`)];
        if (langs.includes('vue')) {
            modules.push('@markuplint/vue-spec');
        }
        if (langs.includes('jsx')) {
            modules.push('@markuplint/react-spec');
        }
        const result = await (0, install_module_1.installModule)(modules, true).catch(e => new Error(e));
        if (result instanceof Error) {
            util_2.error.exit();
            return;
        }
        if (result.alreadyExists) {
            (0, util_2.write)('Modules are installed already.');
        }
        else {
            (0, util_2.write)('✨ Success');
        }
    }
}
exports.initialize = initialize;
