// give it a pattern, and it'll be able to tell you if
// a given path should be ignored.
// Ignoring a path ignores its children if the pattern ends in /**
// Ignores are always parsed in dot:true mode
import { Minimatch } from 'minimatch';
import { Pattern } from './pattern.js';
const defaultPlatform = typeof process === 'object' &&
    process &&
    typeof process.platform === 'string'
    ? process.platform
    : 'linux';
/**
 * Class used to process ignored patterns
 */
export class Ignore {
    relative;
    relativeChildren;
    absolute;
    absoluteChildren;
    constructor(ignored, { nobrace, nocase, noext, noglobstar, platform = defaultPlatform, }) {
        this.relative = [];
        this.absolute = [];
        this.relativeChildren = [];
        this.absoluteChildren = [];
        const mmopts = {
            dot: true,
            nobrace,
            nocase,
            noext,
            noglobstar,
            optimizationLevel: 2,
            platform,
            nocomment: true,
            nonegate: true,
        };
        // this is a little weird, but it gives us a clean set of optimized
        // minimatch matchers, without getting tripped up if one of them
        // ends in /** inside a brace section, and it's only inefficient at
        // the start of the walk, not along it.
        // It'd be nice if the Pattern class just had a .test() method, but
        // handling globstars is a bit of a pita, and that code already lives
        // in minimatch anyway.
        // Another way would be if maybe Minimatch could take its set/globParts
        // as an option, and then we could at least just use Pattern to test
        // for absolute-ness.
        // Yet another way, Minimatch could take an array of glob strings, and
        // a cwd option, and do the right thing.
        for (const ign of ignored) {
            const mm = new Minimatch(ign, mmopts);
            for (let i = 0; i < mm.set.length; i++) {
                const parsed = mm.set[i];
                const globParts = mm.globParts[i];
                /* c8 ignore start */
                if (!parsed || !globParts) {
                    throw new Error('invalid pattern object');
                }
                // strip off leading ./ portions
                // https://github.com/isaacs/node-glob/issues/570
                while (parsed[0] === '.' && globParts[0] === '.') {
                    parsed.shift();
                    globParts.shift();
                }
                /* c8 ignore stop */
                const p = new Pattern(parsed, globParts, 0, platform);
                const m = new Minimatch(p.globString(), mmopts);
                const children = globParts[globParts.length - 1] === '**';
                const absolute = p.isAbsolute();
                if (absolute)
                    this.absolute.push(m);
                else
                    this.relative.push(m);
                if (children) {
                    if (absolute)
                        this.absoluteChildren.push(m);
                    else
                        this.relativeChildren.push(m);
                }
            }
        }
    }
    ignored(p) {
        const fullpath = p.fullpath();
        const fullpaths = `${fullpath}/`;
        const relative = p.relative() || '.';
        const relatives = `${relative}/`;
        for (const m of this.relative) {
            if (m.match(relative) || m.match(relatives))
                return true;
        }
        for (const m of this.absolute) {
            if (m.match(fullpath) || m.match(fullpaths))
                return true;
        }
        return false;
    }
    childrenIgnored(p) {
        const fullpath = p.fullpath() + '/';
        const relative = (p.relative() || '.') + '/';
        for (const m of this.relativeChildren) {
            if (m.match(relative))
                return true;
        }
        for (const m of this.absoluteChildren) {
            if (m.match(fullpath))
                return true;
        }
        return false;
    }
}
//# sourceMappingURL=ignore.js.map