"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());
    });
};
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
    result["default"] = mod;
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const Eslint = __importStar(require("eslint"));
const Walk = __importStar(require("walk"));
const Path = __importStar(require("path"));
const Mustache = __importStar(require("mustache"));
const Stylelint = __importStar(require("stylelint"));
const Project = __importStar(require("../../project/src"));
const styleConfig = require('stylelint-plugin-antcube');
const AC_LINT_FILE_MESSAGE = `
[FILE]: {{&filePath}}
    [error({{&errorCount}}) warning({{&warningCount}})]
    {{#messages}}
    *   [{{&severity}}] ({{&line}}:{{&column}}) {{&message}} <{{&ruleId}}>
{{/messages}}`;
class ACLint {
    lintProject(path) {
        return __awaiter(this, void 0, void 0, function* () {
            const project = new Project.ACProject(path);
            if (project.pkg && project.pkg.cube && project.pkg.cube.lint === 'off') {
                return Promise.resolve({
                    errorCount: 0,
                    warningCount: 0,
                    message: '跳过语法检测'
                });
            }
            if (project.pkg && project.pkg.type === 'templates') {
                return yield this.lintTemplates(path, project);
            }
            else {
                return Promise.resolve({
                    errorCount: 0,
                    warningCount: 0,
                    message: ''
                });
            }
        });
    }
    lintTemplates(path, project) {
        return __awaiter(this, void 0, void 0, function* () {
            const paths = new Array();
            Walk.walkSync(path, {
                listeners: {
                    file: (root, names, next) => {
                        const fpath = Path.join(root, names.name);
                        const finfo = Path.parse(fpath);
                        if (finfo.ext === '.vue') {
                            paths.push(fpath);
                        }
                        next();
                    },
                    errors: (root, names, next) => {
                        next();
                    }
                }
            });
            //  ES-LINT
            const esReport = this.eslintEngine(project).executeOnFiles(paths);
            const esFormated = yield this.formatESLintReport(esReport);
            //  STYLE-LINT
            const styleReport = yield Stylelint.lint({
                config: this.stylelintConfig(project),
                files: paths
            });
            const styleFormated = yield this.formatStyleLintReport(styleReport, project);
            let styleErrorCount = 0;
            styleReport.results.forEach(ele => {
                styleErrorCount += ele.warnings.length;
            });
            const errorCount = esReport.errorCount + styleErrorCount;
            const warningCount = esReport.warningCount;
            const result = [
                `antcube-lint found: error(${errorCount}) warning(${warningCount})\n`,
                esFormated,
                styleFormated
            ].join('');
            return Promise.resolve({
                errorCount,
                warningCount,
                message: result
            });
        });
    }
    formatESLintReport(report) {
        return __awaiter(this, void 0, void 0, function* () {
            if (report.errorCount === 0 && report.warningCount === 0) {
                return Promise.resolve('');
            }
            const messages = new Array();
            for (let index = 0; index < report.results.length; index++) {
                const file = report.results[index];
                let message = Mustache.render(AC_LINT_FILE_MESSAGE, file);
                message = message.split('*   [1]').join('*   [WARN]');
                message = message.split('*   [2]').join('*   [ERRO]');
                messages.push(message);
            }
            return Promise.resolve(messages.join(''));
        });
    }
    formatStyleLintReport(report, project) {
        return __awaiter(this, void 0, void 0, function* () {
            if (!report.errored) {
                return Promise.resolve('');
            }
            const messages = new Array();
            for (let index = 0; index < report.results.length; index++) {
                const rep = report.results[index];
                const filemsgs = new Array();
                rep.warnings.forEach((msg) => {
                    filemsgs.push({
                        severity: 'ERRO',
                        line: msg.line,
                        column: msg.column,
                        message: msg.text,
                        ruleId: msg.rule
                    });
                });
                messages.push(Mustache.render(AC_LINT_FILE_MESSAGE, {
                    filePath: rep.source,
                    errorCount: rep.warnings.length,
                    warningCount: 0,
                    messages: filemsgs
                }));
            }
            return Promise.resolve(messages.join(''));
        });
    }
    eslintEngine(project) {
        let config = {
            useEslintrc: true,
            parser: 'vue-eslint-parser',
            parserOptions: {
                ecmaVersion: 2015
            },
            plugins: ['eslint-plugin-antcube'],
            rules: {
                "antcube/falcon-buildin-component": 'error',
                "antcube/falcon-component-attribute": 'error',
                "antcube/falcon-component-event": 'error',
                "antcube/falcon-valid-expression": 'error'
            }
        };
        if (project.pkg && project.pkg.cube) {
            let rules = Object.assign({}, config.rules);
            if (project.pkg.cube.rules) {
                rules = Object.assign(config.rules, this.filterRules(project.pkg.cube.rules, (key, value) => { return key.startsWith('antcube/falcon-'); }));
            }
            if (project.pkg.cube.widgets) {
                rules['antcube/falcon-buildin-component'] = [rules['antcube/falcon-buildin-component'], project.pkg.cube.widgets];
            }
            config = Object.assign(config, { rules });
        }
        return new Eslint.CLIEngine(config);
    }
    stylelintConfig(project) {
        let config = styleConfig;
        if (project.pkg && project.pkg.cube && project.pkg.cube.rules) {
            const rules = this.filterRules(config.rules, (key, value) => {
                const rl = project.pkg.cube.rules[key];
                return rl && rl === 'off' ? false : true;
            });
            config = Object.assign(config, { rules });
        }
        return styleConfig;
    }
    filterRules(rules, conditions) {
        const result = new Object();
        for (const key in rules) {
            if (rules.hasOwnProperty(key)) {
                if (conditions(key, rules[key])) {
                    result[key] = rules[key];
                }
            }
        }
        return result;
    }
}
exports.ACLint = ACLint;
//# sourceMappingURL=lint.js.map