/**
 * @fileoverview Config file operations. This file must be usable in the browser,
 * so no Node-specific code can be here.
 * @author Nicholas C. Zakas
 */
"use strict";

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

const minimatch = require("minimatch"),
    path = require("path");

const debug = require("debug")("eslint:config-ops");

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

const RULE_SEVERITY_STRINGS = ["off", "warn", "error"],
    RULE_SEVERITY = RULE_SEVERITY_STRINGS.reduce((map, value, index) => {
        map[value] = index;
        return map;
    }, {}),
    VALID_SEVERITIES = [0, 1, 2, "off", "warn", "error"];

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

module.exports = {

    /**
     * Creates an empty configuration object suitable for merging as a base.
     * @returns {Object} A configuration object.
     */
    createEmptyConfig() {
        return {
            globals: {},
            env: {},
            rules: {},
            parserOptions: {}
        };
    },

    /**
     * Creates an environment config based on the specified environments.
     * @param {Object<string,boolean>} env The environment settings.
     * @param {Environments} envContext The environment context.
     * @returns {Object} A configuration object with the appropriate rules and globals
     *      set.
     */
    createEnvironmentConfig(env, envContext) {

        const envConfig = this.createEmptyConfig();

        if (env) {

            envConfig.env = env;

            Object.keys(env).filter(name => env[name]).forEach(name => {
                const environment = envContext.get(name);

                if (environment) {
                    debug(`Creating config for environment ${name}`);
                    if (environment.globals) {
                        Object.assign(envConfig.globals, environment.globals);
                    }

                    if (environment.parserOptions) {
                        Object.assign(envConfig.parserOptions, environment.parserOptions);
                    }
                }
            });
        }

        return envConfig;
    },

    /**
     * Given a config with environment settings, applies the globals and
     * ecmaFeatures to the configuration and returns the result.
     * @param {Object} config The configuration information.
     * @param {Environments} envContent env context.
     * @returns {Object} The updated configuration information.
     */
    applyEnvironments(config, envContent) {
        if (config.env && typeof config.env === "object") {
            debug("Apply environment settings to config");
            return this.merge(this.createEnvironmentConfig(config.env, envContent), config);
        }

        return config;
    },

    /**
     * Merges two config objects. This will not only add missing keys, but will also modify values to match.
     * @param {Object} target config object
     * @param {Object} src config object. Overrides in this config object will take priority over base.
     * @param {boolean} [combine] Whether to combine arrays or not
     * @param {boolean} [isRule] Whether its a rule
     * @returns {Object} merged config object.
     */
    merge: function deepmerge(target, src, combine, isRule) {

        /*
         * The MIT License (MIT)
         *
         * Copyright (c) 2012 Nicholas Fisher
         *
         * Permission is hereby granted, free of charge, to any person obtaining a copy
         * of this software and associated documentation files (the "Software"), to deal
         * in the Software without restriction, including without limitation the rights
         * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         * copies of the Software, and to permit persons to whom the Software is
         * furnished to do so, subject to the following conditions:
         *
         * The above copyright notice and this permission notice shall be included in
         * all copies or substantial portions of the Software.
         *
         * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
         * THE SOFTWARE.
         */

        /*
         * This code is taken from deepmerge repo
         * (https://github.com/KyleAMathews/deepmerge)
         * and modified to meet our needs.
         */
        const array = Array.isArray(src) || Array.isArray(target);
        let dst = array && [] || {};

        if (array) {
            const resolvedTarget = target || [];

            // src could be a string, so check for array
            if (isRule && Array.isArray(src) && src.length > 1) {
                dst = dst.concat(src);
            } else {
                dst = dst.concat(resolvedTarget);
            }
            const resolvedSrc = typeof src === "object" ? src : [src];

            Object.keys(resolvedSrc).forEach((_, i) => {
                const e = resolvedSrc[i];

                if (typeof dst[i] === "undefined") {
                    dst[i] = e;
                } else if (typeof e === "object") {
                    if (isRule) {
                        dst[i] = e;
                    } else {
                        dst[i] = deepmerge(resolvedTarget[i], e, combine, isRule);
                    }
                } else {
                    if (!combine) {
                        dst[i] = e;
                    } else {
                        if (dst.indexOf(e) === -1) {
                            dst.push(e);
                        }
                    }
                }
            });
        } else {
            if (target && typeof target === "object") {
                Object.keys(target).forEach(key => {
                    dst[key] = target[key];
                });
            }
            Object.keys(src).forEach(key => {
                if (key === "overrides") {
                    dst[key] = (target[key] || []).concat(src[key] || []);
                } else if (Array.isArray(src[key]) || Array.isArray(target[key])) {
                    dst[key] = deepmerge(target[key], src[key], key === "plugins" || key === "extends", isRule);
                } else if (typeof src[key] !== "object" || !src[key] || key === "exported" || key === "astGlobals") {
                    dst[key] = src[key];
                } else {
                    dst[key] = deepmerge(target[key] || {}, src[key], combine, key === "rules");
                }
            });
        }

        return dst;
    },

    /**
     * Normalizes the severity value of a rule's configuration to a number
     * @param {(number|string|[number, ...*]|[string, ...*])} ruleConfig A rule's configuration value, generally
     * received from the user. A valid config value is either 0, 1, 2, the string "off" (treated the same as 0),
     * the string "warn" (treated the same as 1), the string "error" (treated the same as 2), or an array
     * whose first element is one of the above values. Strings are matched case-insensitively.
     * @returns {(0|1|2)} The numeric severity value if the config value was valid, otherwise 0.
     */
    getRuleSeverity(ruleConfig) {
        const severityValue = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;

        if (severityValue === 0 || severityValue === 1 || severityValue === 2) {
            return severityValue;
        }

        if (typeof severityValue === "string") {
            return RULE_SEVERITY[severityValue.toLowerCase()] || 0;
        }

        return 0;
    },

    /**
     * Converts old-style severity settings (0, 1, 2) into new-style
     * severity settings (off, warn, error) for all rules. Assumption is that severity
     * values have already been validated as correct.
     * @param {Object} config The config object to normalize.
     * @returns {void}
     */
    normalizeToStrings(config) {

        if (config.rules) {
            Object.keys(config.rules).forEach(ruleId => {
                const ruleConfig = config.rules[ruleId];

                if (typeof ruleConfig === "number") {
                    config.rules[ruleId] = RULE_SEVERITY_STRINGS[ruleConfig] || RULE_SEVERITY_STRINGS[0];
                } else if (Array.isArray(ruleConfig) && typeof ruleConfig[0] === "number") {
                    ruleConfig[0] = RULE_SEVERITY_STRINGS[ruleConfig[0]] || RULE_SEVERITY_STRINGS[0];
                }
            });
        }
    },

    /**
     * Determines if the severity for the given rule configuration represents an error.
     * @param {int|string|Array} ruleConfig The configuration for an individual rule.
     * @returns {boolean} True if the rule represents an error, false if not.
     */
    isErrorSeverity(ruleConfig) {

        let severity = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;

        if (typeof severity === "string") {
            severity = RULE_SEVERITY[severity.toLowerCase()] || 0;
        }

        return (typeof severity === "number" && severity === 2);
    },

    /**
     * Checks whether a given config has valid severity or not.
     * @param {number|string|Array} ruleConfig - The configuration for an individual rule.
     * @returns {boolean} `true` if the configuration has valid severity.
     */
    isValidSeverity(ruleConfig) {
        let severity = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;

        if (typeof severity === "string") {
            severity = severity.toLowerCase();
        }
        return VALID_SEVERITIES.indexOf(severity) !== -1;
    },

    /**
     * Checks whether every rule of a given config has valid severity or not.
     * @param {Object} config - The configuration for rules.
     * @returns {boolean} `true` if the configuration has valid severity.
     */
    isEverySeverityValid(config) {
        return Object.keys(config).every(ruleId => this.isValidSeverity(config[ruleId]));
    },

    /**
     * Merges all configurations in a given config vector. A vector is an array of objects, each containing a config
     * file path and a list of subconfig indices that match the current file path. All config data is assumed to be
     * cached.
     * @param {Array<Object>} vector list of config files and their subconfig indices that match the current file path
     * @param {Object} configCache the config cache
     * @returns {Object} config object
     */
    getConfigFromVector(vector, configCache) {

        const cachedConfig = configCache.getMergedVectorConfig(vector);

        if (cachedConfig) {
            return cachedConfig;
        }

        debug("Using config from partial cache");

        const subvector = Array.from(vector);
        let nearestCacheIndex = subvector.length - 1,
            partialCachedConfig;

        while (nearestCacheIndex >= 0) {
            partialCachedConfig = configCache.getMergedVectorConfig(subvector);
            if (partialCachedConfig) {
                break;
            }
            subvector.pop();
            nearestCacheIndex--;
        }

        if (!partialCachedConfig) {
            partialCachedConfig = {};
        }

        let finalConfig = partialCachedConfig;

        // Start from entry immediately following nearest cached config (first uncached entry)
        for (let i = nearestCacheIndex + 1; i < vector.length; i++) {
            finalConfig = this.mergeVectorEntry(finalConfig, vector[i], configCache);
            configCache.setMergedVectorConfig(vector.slice(0, i + 1), finalConfig);
        }

        return finalConfig;
    },

    /**
     * Merges the config options from a single vector entry into the supplied config.
     * @param {Object} config the base config to merge the vector entry's options into
     * @param {Object} vectorEntry a single entry from a vector, consisting of a config file path and an array of
     * matching override indices
     * @param {Object} configCache the config cache
     * @returns {Object} merged config object
     */
    mergeVectorEntry(config, vectorEntry, configCache) {
        const vectorEntryConfig = Object.assign({}, configCache.getConfig(vectorEntry.filePath));
        let mergedConfig = Object.assign({}, config),
            overrides;

        if (vectorEntryConfig.overrides) {
            overrides = vectorEntryConfig.overrides.filter(
                (override, overrideIndex) => vectorEntry.matchingOverrides.indexOf(overrideIndex) !== -1
            );
        } else {
            overrides = [];
        }

        mergedConfig = this.merge(mergedConfig, vectorEntryConfig);

        delete mergedConfig.overrides;

        mergedConfig = overrides.reduce((lastConfig, override) => this.merge(lastConfig, override), mergedConfig);

        if (mergedConfig.filePath) {
            delete mergedConfig.filePath;
            delete mergedConfig.baseDirectory;
        } else if (mergedConfig.files) {
            delete mergedConfig.files;
        }

        return mergedConfig;
    },

    /**
     * Checks that the specified file path matches all of the supplied glob patterns.
     * @param {string} filePath The file path to test patterns against
     * @param {string|string[]} patterns One or more glob patterns, of which at least one should match the file path
     * @param {string|string[]} [excludedPatterns] One or more glob patterns, of which none should match the file path
     * @returns {boolean} True if all the supplied patterns match the file path, false otherwise
     */
    pathMatchesGlobs(filePath, patterns, excludedPatterns) {
        const patternList = [].concat(patterns);
        const excludedPatternList = [].concat(excludedPatterns || []);

        patternList.concat(excludedPatternList).forEach(pattern => {
            if (path.isAbsolute(pattern) || pattern.includes("..")) {
                throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);
            }
        });

        const opts = { matchBase: true };

        return patternList.some(pattern => minimatch(filePath, pattern, opts)) &&
            !excludedPatternList.some(excludedPattern => minimatch(filePath, excludedPattern, opts));
    }
};
