/**
 * @fileoverview `ConfigArray` class.
 *
 * `ConfigArray` class expresses the full of a configuration. It has the entry
 * config file, base config files that were extended, loaded parsers, and loaded
 * plugins.
 *
 * `ConfigArray` class provies three properties and two methods.
 *
 * - `pluginEnvironments`
 * - `pluginProcessors`
 * - `pluginRules`
 *      The `Map` objects that contain the members of all plugins that this
 *      config array contains. Those map objects don't have mutation methods.
 *      Those keys are the member ID such as `pluginId/memberName`.
 * - `isRoot()`
 *      If `true` then this configuration has `root:true` property.
 * - `extractConfig(filePath)`
 *      Extract the final configuration for a given file. This means merging
 *      every config array element which that `criteria` property matched. The
 *      `filePath` argument must be an absolute path.
 *
 * `ConfigArrayFactory` provides the loading logic of config files.
 *
 * @author Toru Nagashima <https://github.com/mysticatea>
 */
"use strict";

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

const { ExtractedConfig } = require("./extracted-config");

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------

// Define types for VSCode IntelliSense.
/** @typedef {import("../../shared/types").Environment} Environment */
/** @typedef {import("../../shared/types").GlobalConf} GlobalConf */
/** @typedef {import("../../shared/types").RuleConf} RuleConf */
/** @typedef {import("../../shared/types").Rule} Rule */
/** @typedef {import("../../shared/types").Plugin} Plugin */
/** @typedef {import("../../shared/types").Processor} Processor */
/** @typedef {import("./config-dependency").DependentParser} DependentParser */
/** @typedef {import("./config-dependency").DependentPlugin} DependentPlugin */
/** @typedef {import("./override-tester")["OverrideTester"]} OverrideTester */

/**
 * @typedef {Object} ConfigArrayElement
 * @property {string} name The name of this config element.
 * @property {string} filePath The path to the source file of this config element.
 * @property {InstanceType<OverrideTester>|null} criteria The tester for the `files` and `excludedFiles` of this config element.
 * @property {Record<string, boolean>|undefined} env The environment settings.
 * @property {Record<string, GlobalConf>|undefined} globals The global variable settings.
 * @property {DependentParser|undefined} parser The parser loader.
 * @property {Object|undefined} parserOptions The parser options.
 * @property {Record<string, DependentPlugin>|undefined} plugins The plugin loaders.
 * @property {string|undefined} processor The processor name to refer plugin's processor.
 * @property {boolean|undefined} root The flag to express root.
 * @property {Record<string, RuleConf>|undefined} rules The rule settings
 * @property {Object|undefined} settings The shared settings.
 */

/**
 * @typedef {Object} ConfigArrayInternalSlots
 * @property {Map<string, ExtractedConfig>} cache The cache to extract configs.
 * @property {ReadonlyMap<string, Environment>|null} envMap The map from environment ID to environment definition.
 * @property {ReadonlyMap<string, Processor>|null} processorMap The map from processor ID to environment definition.
 * @property {ReadonlyMap<string, Rule>|null} ruleMap The map from rule ID to rule definition.
 */

/** @type {WeakMap<ConfigArray, ConfigArrayInternalSlots>} */
const internalSlotsMap = new class extends WeakMap {
    get(key) {
        let value = super.get(key);

        if (!value) {
            value = {
                cache: new Map(),
                envMap: null,
                processorMap: null,
                ruleMap: null
            };
            super.set(key, value);
        }

        return value;
    }
}();

/**
 * Get the indices which are matched to a given file.
 * @param {ConfigArrayElement[]} elements The elements.
 * @param {string} filePath The path to a target file.
 * @returns {number[]} The indices.
 */
function getMatchedIndices(elements, filePath) {
    const indices = [];

    for (let i = elements.length - 1; i >= 0; --i) {
        const element = elements[i];

        if (!element.criteria || element.criteria.test(filePath)) {
            indices.push(i);
        }
    }

    return indices;
}

/**
 * Check if a value is a non-null object.
 * @param {any} x The value to check.
 * @returns {boolean} `true` if the value is a non-null object.
 */
function isNonNullObject(x) {
    return typeof x === "object" && x !== null;
}

/**
 * Merge two objects.
 *
 * Assign every property values of `y` to `x` if `x` doesn't have the property.
 * If `x`'s property value is an object, it does recursive.
 *
 * @param {Object} target The destination to merge
 * @param {Object|undefined} source The source to merge.
 * @returns {void}
 */
function mergeWithoutOverwrite(target, source) {
    if (!isNonNullObject(source)) {
        return;
    }

    for (const key of Object.keys(source)) {
        if (key === "__proto__") {
            continue;
        }

        if (isNonNullObject(target[key])) {
            mergeWithoutOverwrite(target[key], source[key]);
        } else if (target[key] === void 0) {
            if (isNonNullObject(source[key])) {
                target[key] = Array.isArray(source[key]) ? [] : {};
                mergeWithoutOverwrite(target[key], source[key]);
            } else if (source[key] !== void 0) {
                target[key] = source[key];
            }
        }
    }
}

/**
 * Merge plugins.
 * `target`'s definition is prior to `source`'s.
 *
 * @param {Record<string, DependentPlugin>} target The destination to merge
 * @param {Record<string, DependentPlugin>|undefined} source The source to merge.
 * @returns {void}
 */
function mergePlugins(target, source) {
    if (!isNonNullObject(source)) {
        return;
    }

    for (const key of Object.keys(source)) {
        if (key === "__proto__") {
            continue;
        }
        const targetValue = target[key];
        const sourceValue = source[key];

        // Adopt the plugin which was found at first.
        if (targetValue === void 0) {
            if (sourceValue.error) {
                throw sourceValue.error;
            }
            target[key] = sourceValue;
        }
    }
}

/**
 * Merge rule configs.
 * `target`'s definition is prior to `source`'s.
 *
 * @param {Record<string, Array>} target The destination to merge
 * @param {Record<string, RuleConf>|undefined} source The source to merge.
 * @returns {void}
 */
function mergeRuleConfigs(target, source) {
    if (!isNonNullObject(source)) {
        return;
    }

    for (const key of Object.keys(source)) {
        if (key === "__proto__") {
            continue;
        }
        const targetDef = target[key];
        const sourceDef = source[key];

        // Adopt the rule config which was found at first.
        if (targetDef === void 0) {
            if (Array.isArray(sourceDef)) {
                target[key] = [...sourceDef];
            } else {
                target[key] = [sourceDef];
            }

        /*
         * If the first found rule config is severity only and the current rule
         * config has options, merge the severity and the options.
         */
        } else if (
            targetDef.length === 1 &&
            Array.isArray(sourceDef) &&
            sourceDef.length >= 2
        ) {
            targetDef.push(...sourceDef.slice(1));
        }
    }
}

/**
 * Create the extracted config.
 * @param {ConfigArray} instance The config elements.
 * @param {number[]} indices The indices to use.
 * @returns {ExtractedConfig} The extracted config.
 */
function createConfig(instance, indices) {
    const config = new ExtractedConfig();

    // Merge elements.
    for (const index of indices) {
        const element = instance[index];

        // Adopt the parser which was found at first.
        if (!config.parser && element.parser) {
            if (element.parser.error) {
                throw element.parser.error;
            }
            config.parser = element.parser;
        }

        // Adopt the processor which was found at first.
        if (!config.processor && element.processor) {
            config.processor = element.processor;
        }

        // Merge others.
        mergeWithoutOverwrite(config.env, element.env);
        mergeWithoutOverwrite(config.globals, element.globals);
        mergeWithoutOverwrite(config.parserOptions, element.parserOptions);
        mergeWithoutOverwrite(config.settings, element.settings);
        mergePlugins(config.plugins, element.plugins);
        mergeRuleConfigs(config.rules, element.rules);
    }

    return config;
}

/**
 * Collect definitions.
 * @template T, U
 * @param {string} pluginId The plugin ID for prefix.
 * @param {Record<string,T>} defs The definitions to collect.
 * @param {Map<string, U>} map The map to output.
 * @param {function(T): U} [normalize] The normalize function for each value.
 * @returns {void}
 */
function collect(pluginId, defs, map, normalize) {
    if (defs) {
        const prefix = pluginId && `${pluginId}/`;

        for (const [key, value] of Object.entries(defs)) {
            map.set(
                `${prefix}${key}`,
                normalize ? normalize(value) : value
            );
        }
    }
}

/**
 * Normalize a rule definition.
 * @param {Function|Rule} rule The rule definition to normalize.
 * @returns {Rule} The normalized rule definition.
 */
function normalizePluginRule(rule) {
    return typeof rule === "function" ? { create: rule } : rule;
}

/**
 * Delete the mutation methods from a given map.
 * @param {Map<any, any>} map The map object to delete.
 * @returns {void}
 */
function deleteMutationMethods(map) {
    Object.defineProperties(map, {
        clear: { configurable: true, value: void 0 },
        delete: { configurable: true, value: void 0 },
        set: { configurable: true, value: void 0 }
    });
}

/**
 * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.
 * @param {ConfigArrayElement[]} elements The config elements.
 * @param {ConfigArrayInternalSlots} slots The internal slots.
 * @returns {void}
 */
function initPluginMemberMaps(elements, slots) {
    const processed = new Set();

    slots.envMap = new Map();
    slots.processorMap = new Map();
    slots.ruleMap = new Map();

    for (const element of elements) {
        if (!element.plugins) {
            continue;
        }

        for (const [pluginId, value] of Object.entries(element.plugins)) {
            const plugin = value.definition;

            if (!plugin || processed.has(pluginId)) {
                continue;
            }
            processed.add(pluginId);

            collect(pluginId, plugin.environments, slots.envMap);
            collect(pluginId, plugin.processors, slots.processorMap);
            collect(pluginId, plugin.rules, slots.ruleMap, normalizePluginRule);
        }
    }

    deleteMutationMethods(slots.envMap);
    deleteMutationMethods(slots.processorMap);
    deleteMutationMethods(slots.ruleMap);
}

/**
 * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.
 * @param {ConfigArray} instance The config elements.
 * @returns {ConfigArrayInternalSlots} The extracted config.
 */
function ensurePluginMemberMaps(instance) {
    const slots = internalSlotsMap.get(instance);

    if (!slots.ruleMap) {
        initPluginMemberMaps(instance, slots);
    }

    return slots;
}

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

/**
 * The Config Array.
 *
 * `ConfigArray` instance contains all settings, parsers, and plugins.
 * You need to call `ConfigArray#extractConfig(filePath)` method in order to
 * extract, merge and get only the config data which is related to an arbitrary
 * file.
 *
 * @extends {Array<ConfigArrayElement>}
 */
class ConfigArray extends Array {

    /**
     * Get the plugin environments.
     * The returned map cannot be mutated.
     * @type {ReadonlyMap<string, Environment>} The plugin environments.
     */
    get pluginEnvironments() {
        return ensurePluginMemberMaps(this).envMap;
    }

    /**
     * Get the plugin processors.
     * The returned map cannot be mutated.
     * @type {ReadonlyMap<string, Processor>} The plugin processors.
     */
    get pluginProcessors() {
        return ensurePluginMemberMaps(this).processorMap;
    }

    /**
     * Get the plugin rules.
     * The returned map cannot be mutated.
     * @returns {ReadonlyMap<string, Rule>} The plugin rules.
     */
    get pluginRules() {
        return ensurePluginMemberMaps(this).ruleMap;
    }

    /**
     * Check if this config has `root` flag.
     * @returns {boolean} `true` if this config array is root.
     */
    isRoot() {
        for (let i = this.length - 1; i >= 0; --i) {
            const root = this[i].root;

            if (typeof root === "boolean") {
                return root;
            }
        }
        return false;
    }

    /**
     * Extract the config data which is related to a given file.
     * @param {string} filePath The absolute path to the target file.
     * @returns {ExtractedConfig} The extracted config data.
     */
    extractConfig(filePath) {
        const { cache } = internalSlotsMap.get(this);
        const indices = getMatchedIndices(this, filePath);
        const cacheKey = indices.join(",");

        if (!cache.has(cacheKey)) {
            cache.set(cacheKey, createConfig(this, indices));
        }

        return cache.get(cacheKey);
    }
}

const exportObject = {
    ConfigArray,

    /**
     * Get the used extracted configs.
     * CLIEngine will use this method to collect used deprecated rules.
     * @param {ConfigArray} instance The config array object to get.
     * @returns {ExtractedConfig[]} The used extracted configs.
     * @private
     */
    getUsedExtractedConfigs(instance) {
        const { cache } = internalSlotsMap.get(instance);

        return Array.from(cache.values());
    }
};

module.exports = exportObject;
