/**
 * @fileoverview `FileEnumerator` class.
 *
 * `FileEnumerator` class has two responsibilities:
 *
 * 1. Find target files by processing glob patterns.
 * 2. Tie each target file and appropriate configuration.
 *
 * It provides a method:
 *
 * - `iterateFiles(patterns)`
 *     Iterate files which are matched by given patterns together with the
 *     corresponded configuration. This is for `CLIEngine#executeOnFiles()`.
 *     While iterating files, it loads the configuration file of each directory
 *     before iterate files on the directory, so we can use the configuration
 *     files to determine target files.
 *
 * @example
 * const enumerator = new FileEnumerator();
 * const linter = new Linter();
 *
 * for (const { config, filePath } of enumerator.iterateFiles(["*.js"])) {
 *     const code = fs.readFileSync(filePath, "utf8");
 *     const messages = linter.verify(code, config, filePath);
 *
 *     console.log(messages);
 * }
 *
 * @author Toru Nagashima <https://github.com/mysticatea>
 */
"use strict";

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

const fs = require("fs");
const path = require("path");
const getGlobParent = require("glob-parent");
const isGlob = require("is-glob");
const escapeRegExp = require("escape-string-regexp");
const { Minimatch } = require("minimatch");

const {
    Legacy: {
        IgnorePattern,
        CascadingConfigArrayFactory
    }
} = require("@eslint/eslintrc");
const debug = require("debug")("eslint:file-enumerator");

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

const minimatchOpts = { dot: true, matchBase: true };
const dotfilesPattern = /(?:(?:^\.)|(?:[/\\]\.))[^/\\.].*/u;
const NONE = 0;
const IGNORED_SILENTLY = 1;
const IGNORED = 2;

// For VSCode intellisense
/** @typedef {ReturnType<CascadingConfigArrayFactory.getConfigArrayForFile>} ConfigArray */

/**
 * @typedef {Object} FileEnumeratorOptions
 * @property {CascadingConfigArrayFactory} [configArrayFactory] The factory for config arrays.
 * @property {string} [cwd] The base directory to start lookup.
 * @property {string[]} [extensions] The extensions to match files for directory patterns.
 * @property {boolean} [globInputPaths] Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
 * @property {boolean} [ignore] The flag to check ignored files.
 * @property {string[]} [rulePaths] The value of `--rulesdir` option.
 */

/**
 * @typedef {Object} FileAndConfig
 * @property {string} filePath The path to a target file.
 * @property {ConfigArray} config The config entries of that file.
 * @property {boolean} ignored If `true` then this file should be ignored and warned because it was directly specified.
 */

/**
 * @typedef {Object} FileEntry
 * @property {string} filePath The path to a target file.
 * @property {ConfigArray} config The config entries of that file.
 * @property {NONE|IGNORED_SILENTLY|IGNORED} flag The flag.
 * - `NONE` means the file is a target file.
 * - `IGNORED_SILENTLY` means the file should be ignored silently.
 * - `IGNORED` means the file should be ignored and warned because it was directly specified.
 */

/**
 * @typedef {Object} FileEnumeratorInternalSlots
 * @property {CascadingConfigArrayFactory} configArrayFactory The factory for config arrays.
 * @property {string} cwd The base directory to start lookup.
 * @property {RegExp|null} extensionRegExp The RegExp to test if a string ends with specific file extensions.
 * @property {boolean} globInputPaths Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
 * @property {boolean} ignoreFlag The flag to check ignored files.
 * @property {(filePath:string, dot:boolean) => boolean} defaultIgnores The default predicate function to ignore files.
 */

/** @type {WeakMap<FileEnumerator, FileEnumeratorInternalSlots>} */
const internalSlotsMap = new WeakMap();

/**
 * Check if a string is a glob pattern or not.
 * @param {string} pattern A glob pattern.
 * @returns {boolean} `true` if the string is a glob pattern.
 */
function isGlobPattern(pattern) {
    return isGlob(path.sep === "\\" ? pattern.replace(/\\/gu, "/") : pattern);
}

/**
 * Get stats of a given path.
 * @param {string} filePath The path to target file.
 * @throws {Error} As may be thrown by `fs.statSync`.
 * @returns {fs.Stats|null} The stats.
 * @private
 */
function statSafeSync(filePath) {
    try {
        return fs.statSync(filePath);
    } catch (error) {
        /* istanbul ignore next */
        if (error.code !== "ENOENT") {
            throw error;
        }
        return null;
    }
}

/**
 * Get filenames in a given path to a directory.
 * @param {string} directoryPath The path to target directory.
 * @throws {Error} As may be thrown by `fs.readdirSync`.
 * @returns {import("fs").Dirent[]} The filenames.
 * @private
 */
function readdirSafeSync(directoryPath) {
    try {
        return fs.readdirSync(directoryPath, { withFileTypes: true });
    } catch (error) {
        /* istanbul ignore next */
        if (error.code !== "ENOENT") {
            throw error;
        }
        return [];
    }
}

/**
 * Create a `RegExp` object to detect extensions.
 * @param {string[] | null} extensions The extensions to create.
 * @returns {RegExp | null} The created `RegExp` object or null.
 */
function createExtensionRegExp(extensions) {
    if (extensions) {
        const normalizedExts = extensions.map(ext => escapeRegExp(
            ext.startsWith(".")
                ? ext.slice(1)
                : ext
        ));

        return new RegExp(
            `.\\.(?:${normalizedExts.join("|")})$`,
            "u"
        );
    }
    return null;
}

/**
 * The error type when no files match a glob.
 */
class NoFilesFoundError extends Error {

    /**
     * @param {string} pattern The glob pattern which was not found.
     * @param {boolean} globDisabled If `true` then the pattern was a glob pattern, but glob was disabled.
     */
    constructor(pattern, globDisabled) {
        super(`No files matching '${pattern}' were found${globDisabled ? " (glob was disabled)" : ""}.`);
        this.messageTemplate = "file-not-found";
        this.messageData = { pattern, globDisabled };
    }
}

/**
 * The error type when there are files matched by a glob, but all of them have been ignored.
 */
class AllFilesIgnoredError extends Error {

    /**
     * @param {string} pattern The glob pattern which was not found.
     */
    constructor(pattern) {
        super(`All files matched by '${pattern}' are ignored.`);
        this.messageTemplate = "all-files-ignored";
        this.messageData = { pattern };
    }
}

/**
 * This class provides the functionality that enumerates every file which is
 * matched by given glob patterns and that configuration.
 */
class FileEnumerator {

    /**
     * Initialize this enumerator.
     * @param {FileEnumeratorOptions} options The options.
     */
    constructor({
        cwd = process.cwd(),
        configArrayFactory = new CascadingConfigArrayFactory({
            cwd,
            eslintRecommendedPath: path.resolve(__dirname, "../../conf/eslint-recommended.js"),
            eslintAllPath: path.resolve(__dirname, "../../conf/eslint-all.js")
        }),
        extensions = null,
        globInputPaths = true,
        errorOnUnmatchedPattern = true,
        ignore = true
    } = {}) {
        internalSlotsMap.set(this, {
            configArrayFactory,
            cwd,
            defaultIgnores: IgnorePattern.createDefaultIgnore(cwd),
            extensionRegExp: createExtensionRegExp(extensions),
            globInputPaths,
            errorOnUnmatchedPattern,
            ignoreFlag: ignore
        });
    }

    /**
     * Check if a given file is target or not.
     * @param {string} filePath The path to a candidate file.
     * @param {ConfigArray} [providedConfig] Optional. The configuration for the file.
     * @returns {boolean} `true` if the file is a target.
     */
    isTargetPath(filePath, providedConfig) {
        const {
            configArrayFactory,
            extensionRegExp
        } = internalSlotsMap.get(this);

        // If `--ext` option is present, use it.
        if (extensionRegExp) {
            return extensionRegExp.test(filePath);
        }

        // `.js` file is target by default.
        if (filePath.endsWith(".js")) {
            return true;
        }

        // use `overrides[].files` to check additional targets.
        const config =
            providedConfig ||
            configArrayFactory.getConfigArrayForFile(
                filePath,
                { ignoreNotFoundError: true }
            );

        return config.isAdditionalTargetPath(filePath);
    }

    /**
     * Iterate files which are matched by given glob patterns.
     * @param {string|string[]} patternOrPatterns The glob patterns to iterate files.
     * @throws {NoFilesFoundError|AllFilesIgnoredError} On an unmatched pattern.
     * @returns {IterableIterator<FileAndConfig>} The found files.
     */
    *iterateFiles(patternOrPatterns) {
        const { globInputPaths, errorOnUnmatchedPattern } = internalSlotsMap.get(this);
        const patterns = Array.isArray(patternOrPatterns)
            ? patternOrPatterns
            : [patternOrPatterns];

        debug("Start to iterate files: %o", patterns);

        // The set of paths to remove duplicate.
        const set = new Set();

        for (const pattern of patterns) {
            let foundRegardlessOfIgnored = false;
            let found = false;

            // Skip empty string.
            if (!pattern) {
                continue;
            }

            // Iterate files of this pattern.
            for (const { config, filePath, flag } of this._iterateFiles(pattern)) {
                foundRegardlessOfIgnored = true;
                if (flag === IGNORED_SILENTLY) {
                    continue;
                }
                found = true;

                // Remove duplicate paths while yielding paths.
                if (!set.has(filePath)) {
                    set.add(filePath);
                    yield {
                        config,
                        filePath,
                        ignored: flag === IGNORED
                    };
                }
            }

            // Raise an error if any files were not found.
            if (errorOnUnmatchedPattern) {
                if (!foundRegardlessOfIgnored) {
                    throw new NoFilesFoundError(
                        pattern,
                        !globInputPaths && isGlob(pattern)
                    );
                }
                if (!found) {
                    throw new AllFilesIgnoredError(pattern);
                }
            }
        }

        debug(`Complete iterating files: ${JSON.stringify(patterns)}`);
    }

    /**
     * Iterate files which are matched by a given glob pattern.
     * @param {string} pattern The glob pattern to iterate files.
     * @returns {IterableIterator<FileEntry>} The found files.
     */
    _iterateFiles(pattern) {
        const { cwd, globInputPaths } = internalSlotsMap.get(this);
        const absolutePath = path.resolve(cwd, pattern);
        const isDot = dotfilesPattern.test(pattern);
        const stat = statSafeSync(absolutePath);

        if (stat && stat.isDirectory()) {
            return this._iterateFilesWithDirectory(absolutePath, isDot);
        }
        if (stat && stat.isFile()) {
            return this._iterateFilesWithFile(absolutePath);
        }
        if (globInputPaths && isGlobPattern(pattern)) {
            return this._iterateFilesWithGlob(absolutePath, isDot);
        }

        return [];
    }

    /**
     * Iterate a file which is matched by a given path.
     * @param {string} filePath The path to the target file.
     * @returns {IterableIterator<FileEntry>} The found files.
     * @private
     */
    _iterateFilesWithFile(filePath) {
        debug(`File: ${filePath}`);

        const { configArrayFactory } = internalSlotsMap.get(this);
        const config = configArrayFactory.getConfigArrayForFile(filePath);
        const ignored = this._isIgnoredFile(filePath, { config, direct: true });
        const flag = ignored ? IGNORED : NONE;

        return [{ config, filePath, flag }];
    }

    /**
     * Iterate files in a given path.
     * @param {string} directoryPath The path to the target directory.
     * @param {boolean} dotfiles If `true` then it doesn't skip dot files by default.
     * @returns {IterableIterator<FileEntry>} The found files.
     * @private
     */
    _iterateFilesWithDirectory(directoryPath, dotfiles) {
        debug(`Directory: ${directoryPath}`);

        return this._iterateFilesRecursive(
            directoryPath,
            { dotfiles, recursive: true, selector: null }
        );
    }

    /**
     * Iterate files which are matched by a given glob pattern.
     * @param {string} pattern The glob pattern to iterate files.
     * @param {boolean} dotfiles If `true` then it doesn't skip dot files by default.
     * @returns {IterableIterator<FileEntry>} The found files.
     * @private
     */
    _iterateFilesWithGlob(pattern, dotfiles) {
        debug(`Glob: ${pattern}`);

        const directoryPath = path.resolve(getGlobParent(pattern));
        const globPart = pattern.slice(directoryPath.length + 1);

        /*
         * recursive if there are `**` or path separators in the glob part.
         * Otherwise, patterns such as `src/*.js`, it doesn't need recursive.
         */
        const recursive = /\*\*|\/|\\/u.test(globPart);
        const selector = new Minimatch(pattern, minimatchOpts);

        debug(`recursive? ${recursive}`);

        return this._iterateFilesRecursive(
            directoryPath,
            { dotfiles, recursive, selector }
        );
    }

    /**
     * Iterate files in a given path.
     * @param {string} directoryPath The path to the target directory.
     * @param {Object} options The options to iterate files.
     * @param {boolean} [options.dotfiles] If `true` then it doesn't skip dot files by default.
     * @param {boolean} [options.recursive] If `true` then it dives into sub directories.
     * @param {InstanceType<Minimatch>} [options.selector] The matcher to choose files.
     * @returns {IterableIterator<FileEntry>} The found files.
     * @private
     */
    *_iterateFilesRecursive(directoryPath, options) {
        debug(`Enter the directory: ${directoryPath}`);
        const { configArrayFactory } = internalSlotsMap.get(this);

        /** @type {ConfigArray|null} */
        let config = null;

        // Enumerate the files of this directory.
        for (const entry of readdirSafeSync(directoryPath)) {
            const filePath = path.join(directoryPath, entry.name);
            const fileInfo = entry.isSymbolicLink() ? statSafeSync(filePath) : entry;

            if (!fileInfo) {
                continue;
            }

            // Check if the file is matched.
            if (fileInfo.isFile()) {
                if (!config) {
                    config = configArrayFactory.getConfigArrayForFile(
                        filePath,

                        /*
                         * We must ignore `ConfigurationNotFoundError` at this
                         * point because we don't know if target files exist in
                         * this directory.
                         */
                        { ignoreNotFoundError: true }
                    );
                }
                const matched = options.selector

                    // Started with a glob pattern; choose by the pattern.
                    ? options.selector.match(filePath)

                    // Started with a directory path; choose by file extensions.
                    : this.isTargetPath(filePath, config);

                if (matched) {
                    const ignored = this._isIgnoredFile(filePath, { ...options, config });
                    const flag = ignored ? IGNORED_SILENTLY : NONE;

                    debug(`Yield: ${entry.name}${ignored ? " but ignored" : ""}`);
                    yield {
                        config: configArrayFactory.getConfigArrayForFile(filePath),
                        filePath,
                        flag
                    };
                } else {
                    debug(`Didn't match: ${entry.name}`);
                }

            // Dive into the sub directory.
            } else if (options.recursive && fileInfo.isDirectory()) {
                if (!config) {
                    config = configArrayFactory.getConfigArrayForFile(
                        filePath,
                        { ignoreNotFoundError: true }
                    );
                }
                const ignored = this._isIgnoredFile(
                    filePath + path.sep,
                    { ...options, config }
                );

                if (!ignored) {
                    yield* this._iterateFilesRecursive(filePath, options);
                }
            }
        }

        debug(`Leave the directory: ${directoryPath}`);
    }

    /**
     * Check if a given file should be ignored.
     * @param {string} filePath The path to a file to check.
     * @param {Object} options Options
     * @param {ConfigArray} [options.config] The config for this file.
     * @param {boolean} [options.dotfiles] If `true` then this is not ignore dot files by default.
     * @param {boolean} [options.direct] If `true` then this is a direct specified file.
     * @returns {boolean} `true` if the file should be ignored.
     * @private
     */
    _isIgnoredFile(filePath, {
        config: providedConfig,
        dotfiles = false,
        direct = false
    }) {
        const {
            configArrayFactory,
            defaultIgnores,
            ignoreFlag
        } = internalSlotsMap.get(this);

        if (ignoreFlag) {
            const config =
                providedConfig ||
                configArrayFactory.getConfigArrayForFile(
                    filePath,
                    { ignoreNotFoundError: true }
                );
            const ignores =
                config.extractConfig(filePath).ignores || defaultIgnores;

            return ignores(filePath, dotfiles);
        }

        return !direct && defaultIgnores(filePath, dotfiles);
    }
}

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

module.exports = { FileEnumerator };
