/**
 * @fileoverview Used for creating a suggested configuration based on project code.
 * @author Ian VanSchooten
 */

"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const lodash = require("lodash"),
    recConfig = require("../../conf/eslint-recommended"),
    ConfigOps = require("../shared/config-ops"),
    { Linter } = require("../linter"),
    configRule = require("./config-rule");

const debug = require("debug")("eslint:autoconfig");
const linter = new Linter();

//------------------------------------------------------------------------------
// Data
//------------------------------------------------------------------------------

const MAX_CONFIG_COMBINATIONS = 17, // 16 combinations + 1 for severity only
    RECOMMENDED_CONFIG_NAME = "eslint:recommended";

//------------------------------------------------------------------------------
// Private
//------------------------------------------------------------------------------

/**
 * Information about a rule configuration, in the context of a Registry.
 *
 * @typedef {Object}     registryItem
 * @param   {ruleConfig} config        A valid configuration for the rule
 * @param   {number}     specificity   The number of elements in the ruleConfig array
 * @param   {number}     errorCount    The number of errors encountered when linting with the config
 */

/**
 * This callback is used to measure execution status in a progress bar
 * @callback progressCallback
 * @param {number} The total number of times the callback will be called.
 */

/**
 * Create registryItems for rules
 * @param   {rulesConfig} rulesConfig Hash of rule names and arrays of ruleConfig items
 * @returns {Object}                  registryItems for each rule in provided rulesConfig
 */
function makeRegistryItems(rulesConfig) {
    return Object.keys(rulesConfig).reduce((accumulator, ruleId) => {
        accumulator[ruleId] = rulesConfig[ruleId].map(config => ({
            config,
            specificity: config.length || 1,
            errorCount: void 0
        }));
        return accumulator;
    }, {});
}

/**
 * Creates an object in which to store rule configs and error counts
 *
 * Unless a rulesConfig is provided at construction, the registry will not contain
 * any rules, only methods.  This will be useful for building up registries manually.
 *
 * Registry class
 */
class Registry {

    /**
     * @param {rulesConfig} [rulesConfig] Hash of rule names and arrays of possible configurations
     */
    constructor(rulesConfig) {
        this.rules = (rulesConfig) ? makeRegistryItems(rulesConfig) : {};
    }

    /**
     * Populate the registry with core rule configs.
     *
     * It will set the registry's `rule` property to an object having rule names
     * as keys and an array of registryItems as values.
     *
     * @returns {void}
     */
    populateFromCoreRules() {
        const rulesConfig = configRule.createCoreRuleConfigs();

        this.rules = makeRegistryItems(rulesConfig);
    }

    /**
     * Creates sets of rule configurations which can be used for linting
     * and initializes registry errors to zero for those configurations (side effect).
     *
     * This combines as many rules together as possible, such that the first sets
     * in the array will have the highest number of rules configured, and later sets
     * will have fewer and fewer, as not all rules have the same number of possible
     * configurations.
     *
     * The length of the returned array will be <= MAX_CONFIG_COMBINATIONS.
     *
     * @returns {Object[]}          "rules" configurations to use for linting
     */
    buildRuleSets() {
        let idx = 0;
        const ruleIds = Object.keys(this.rules),
            ruleSets = [];

        /**
         * Add a rule configuration from the registry to the ruleSets
         *
         * This is broken out into its own function so that it doesn't need to be
         * created inside of the while loop.
         *
         * @param   {string} rule The ruleId to add.
         * @returns {void}
         */
        const addRuleToRuleSet = function(rule) {

            /*
             * This check ensures that there is a rule configuration and that
             * it has fewer than the max combinations allowed.
             * If it has too many configs, we will only use the most basic of
             * the possible configurations.
             */
            const hasFewCombos = (this.rules[rule].length <= MAX_CONFIG_COMBINATIONS);

            if (this.rules[rule][idx] && (hasFewCombos || this.rules[rule][idx].specificity <= 2)) {

                /*
                 * If the rule has too many possible combinations, only take
                 * simple ones, avoiding objects.
                 */
                if (!hasFewCombos && typeof this.rules[rule][idx].config[1] === "object") {
                    return;
                }

                ruleSets[idx] = ruleSets[idx] || {};
                ruleSets[idx][rule] = this.rules[rule][idx].config;

                /*
                 * Initialize errorCount to zero, since this is a config which
                 * will be linted.
                 */
                this.rules[rule][idx].errorCount = 0;
            }
        }.bind(this);

        while (ruleSets.length === idx) {
            ruleIds.forEach(addRuleToRuleSet);
            idx += 1;
        }

        return ruleSets;
    }

    /**
     * Remove all items from the registry with a non-zero number of errors
     *
     * Note: this also removes rule configurations which were not linted
     * (meaning, they have an undefined errorCount).
     *
     * @returns {void}
     */
    stripFailingConfigs() {
        const ruleIds = Object.keys(this.rules),
            newRegistry = new Registry();

        newRegistry.rules = Object.assign({}, this.rules);
        ruleIds.forEach(ruleId => {
            const errorFreeItems = newRegistry.rules[ruleId].filter(registryItem => (registryItem.errorCount === 0));

            if (errorFreeItems.length > 0) {
                newRegistry.rules[ruleId] = errorFreeItems;
            } else {
                delete newRegistry.rules[ruleId];
            }
        });

        return newRegistry;
    }

    /**
     * Removes rule configurations which were not included in a ruleSet
     *
     * @returns {void}
     */
    stripExtraConfigs() {
        const ruleIds = Object.keys(this.rules),
            newRegistry = new Registry();

        newRegistry.rules = Object.assign({}, this.rules);
        ruleIds.forEach(ruleId => {
            newRegistry.rules[ruleId] = newRegistry.rules[ruleId].filter(registryItem => (typeof registryItem.errorCount !== "undefined"));
        });

        return newRegistry;
    }

    /**
     * Creates a registry of rules which had no error-free configs.
     * The new registry is intended to be analyzed to determine whether its rules
     * should be disabled or set to warning.
     *
     * @returns {Registry}  A registry of failing rules.
     */
    getFailingRulesRegistry() {
        const ruleIds = Object.keys(this.rules),
            failingRegistry = new Registry();

        ruleIds.forEach(ruleId => {
            const failingConfigs = this.rules[ruleId].filter(registryItem => (registryItem.errorCount > 0));

            if (failingConfigs && failingConfigs.length === this.rules[ruleId].length) {
                failingRegistry.rules[ruleId] = failingConfigs;
            }
        });

        return failingRegistry;
    }

    /**
     * Create an eslint config for any rules which only have one configuration
     * in the registry.
     *
     * @returns {Object} An eslint config with rules section populated
     */
    createConfig() {
        const ruleIds = Object.keys(this.rules),
            config = { rules: {} };

        ruleIds.forEach(ruleId => {
            if (this.rules[ruleId].length === 1) {
                config.rules[ruleId] = this.rules[ruleId][0].config;
            }
        });

        return config;
    }

    /**
     * Return a cloned registry containing only configs with a desired specificity
     *
     * @param   {number} specificity Only keep configs with this specificity
     * @returns {Registry}           A registry of rules
     */
    filterBySpecificity(specificity) {
        const ruleIds = Object.keys(this.rules),
            newRegistry = new Registry();

        newRegistry.rules = Object.assign({}, this.rules);
        ruleIds.forEach(ruleId => {
            newRegistry.rules[ruleId] = this.rules[ruleId].filter(registryItem => (registryItem.specificity === specificity));
        });

        return newRegistry;
    }

    /**
     * Lint SourceCodes against all configurations in the registry, and record results
     *
     * @param   {Object[]} sourceCodes  SourceCode objects for each filename
     * @param   {Object}   config       ESLint config object
     * @param   {progressCallback} [cb] Optional callback for reporting execution status
     * @returns {Registry}              New registry with errorCount populated
     */
    lintSourceCode(sourceCodes, config, cb) {
        let lintedRegistry = new Registry();

        lintedRegistry.rules = Object.assign({}, this.rules);

        const ruleSets = lintedRegistry.buildRuleSets();

        lintedRegistry = lintedRegistry.stripExtraConfigs();

        debug("Linting with all possible rule combinations");

        const filenames = Object.keys(sourceCodes);
        const totalFilesLinting = filenames.length * ruleSets.length;

        filenames.forEach(filename => {
            debug(`Linting file: ${filename}`);

            let ruleSetIdx = 0;

            ruleSets.forEach(ruleSet => {
                const lintConfig = Object.assign({}, config, { rules: ruleSet });
                const lintResults = linter.verify(sourceCodes[filename], lintConfig);

                lintResults.forEach(result => {

                    /*
                     * It is possible that the error is from a configuration comment
                     * in a linted file, in which case there may not be a config
                     * set in this ruleSetIdx.
                     * (https://github.com/eslint/eslint/issues/5992)
                     * (https://github.com/eslint/eslint/issues/7860)
                     */
                    if (
                        lintedRegistry.rules[result.ruleId] &&
                        lintedRegistry.rules[result.ruleId][ruleSetIdx]
                    ) {
                        lintedRegistry.rules[result.ruleId][ruleSetIdx].errorCount += 1;
                    }
                });

                ruleSetIdx += 1;

                if (cb) {
                    cb(totalFilesLinting); // eslint-disable-line callback-return
                }
            });

            // Deallocate for GC
            sourceCodes[filename] = null;
        });

        return lintedRegistry;
    }
}

/**
 * Extract rule configuration into eslint:recommended where possible.
 *
 * This will return a new config with `"extends": "eslint:recommended"` and
 * only the rules which have configurations different from the recommended config.
 *
 * @param   {Object} config config object
 * @returns {Object}        config object using `"extends": "eslint:recommended"`
 */
function extendFromRecommended(config) {
    const newConfig = Object.assign({}, config);

    ConfigOps.normalizeToStrings(newConfig);

    const recRules = Object.keys(recConfig.rules).filter(ruleId => ConfigOps.isErrorSeverity(recConfig.rules[ruleId]));

    recRules.forEach(ruleId => {
        if (lodash.isEqual(recConfig.rules[ruleId], newConfig.rules[ruleId])) {
            delete newConfig.rules[ruleId];
        }
    });
    newConfig.extends = RECOMMENDED_CONFIG_NAME;
    return newConfig;
}


//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------

module.exports = {
    Registry,
    extendFromRecommended
};
