'use strict';

require('should');
var assert = require('assert');
var argv = require('minimist')(process.argv.slice(2));
var minimatch = require('./support/reference');
var mm = require('..');

if ('minimatch' in argv) {
  mm = minimatch;
}

describe('.isMatch()', function() {
  describe('errors:', function() {
    it('should throw on undefined args:', function() {
      (function() {
        mm.isMatch();
      }).should.throw('micromatch.isMatch(): filepath should be a string.');
    });

    it('should throw on bad args:', function() {
      (function() {
        mm.isMatch({});
      }).should.throw('micromatch.isMatch(): filepath should be a string.');
    });
  });

  it('should work like `matcher` when a pattern and opts is passed', function() {
    assert(typeof mm.isMatch('*', {}), 'function');
    assert(mm.isMatch('*', {})('abc'), true);
  });

  it('should escape plus signs to match string literals', function() {
    assert(mm.isMatch('a+b/src/glimini.js', 'a+b/src/*.js'));
    assert(mm.isMatch('+b/src/glimini.js', '+b/src/*.js'));
    assert(mm.isMatch('coffee+/src/glimini.js', 'coffee+/src/*.js'));
    assert(mm.isMatch('coffee+/src/glimini.js', 'coffee+/src/*.js'));
    assert(mm.isMatch('coffee+/src/glimini.js', 'coffee+/src/*'));
  });

  it('should correctly deal with empty globs', function() {
    mm.isMatch('ab', '').should.be.false();
    mm.isMatch('a', '').should.be.false();
    mm.isMatch('.', '').should.be.false();
  });

  it('should match with non-glob patterns', function() {
    mm.isMatch('.', '.').should.be.true();
    mm.isMatch('/a', '/a').should.be.true();
    mm.isMatch('/ab', '/a').should.be.false();
    mm.isMatch('a', 'a').should.be.true();
    mm.isMatch('ab', '/a').should.be.false();
    mm.isMatch('ab', 'a').should.be.false();
    mm.isMatch('ab', 'ab').should.be.true();
    mm.isMatch('abcd', 'cd').should.be.false();
    mm.isMatch('abcd', 'bc').should.be.false();
    mm.isMatch('abcd', 'ab').should.be.false();
  });

  it('should match file names:', function() {
    mm.isMatch('a.b', 'a.b').should.be.true();
    mm.isMatch('a.b', '*.b').should.be.true();
    mm.isMatch('a.b', 'a.*').should.be.true();
    mm.isMatch('a.b', '*.*').should.be.true();
    mm.isMatch('a-b.c-d', 'a*.c*').should.be.true();
    mm.isMatch('a-b.c-d', '*b.*d').should.be.true();
    mm.isMatch('a-b.c-d', '*.*').should.be.true();
    mm.isMatch('a-b.c-d', '*.*-*').should.be.true();
    mm.isMatch('a-b.c-d', '*-*.*-*').should.be.true();
    mm.isMatch('a-b.c-d', '*.c-*').should.be.true();
    mm.isMatch('a-b.c-d', '*.*-d').should.be.true();
    mm.isMatch('a-b.c-d', 'a-*.*-d').should.be.true();
    mm.isMatch('a-b.c-d', '*-b.c-*').should.be.true();
    mm.isMatch('a-b.c-d', '*-b*c-*').should.be.true();

    // false
    mm.isMatch('a-b.c-d', '*-bc-*').should.be.false();
  });

  it('should match with common glob patterns', function() {
    mm.isMatch('/ab', '/*').should.be.true();
    mm.isMatch('/cd', '/*').should.be.true();
    mm.isMatch('ef', '/*').should.be.false();
    mm.isMatch('ab', './*').should.be.false();
    mm.isMatch('ab', '*').should.be.true();
    mm.isMatch('ab', 'ab').should.be.true();
  });

  it('should match files with the given extension:', function() {
    mm.isMatch('.md', '*.md').should.be.false();
    mm.isMatch('.md', '.md').should.be.true();
    mm.isMatch('.c.md', '*.md').should.be.false();
    mm.isMatch('.c.md', '.*.md').should.be.true();
    mm.isMatch('c.md', '*.md').should.be.true();
    mm.isMatch('c.md', '*.md').should.be.true();
    mm.isMatch('a/b/c/c.md', '*.md').should.be.false();
    mm.isMatch('a/b/c.md', 'a/*.md').should.be.false();
    mm.isMatch('a/b/c.md', 'a/*/*.md').should.be.true();
    mm.isMatch('a/b/c.md', '**/*.md').should.be.true();
    mm.isMatch('a/b/c.js', 'a/**/*.*').should.be.true();
  });

  it('should match wildcards:', function() {
    mm.isMatch('a/b/c/z.js', '*.js').should.be.false();
    mm.isMatch('a/b/z.js', '*.js').should.be.false();
    mm.isMatch('a/z.js', '*.js').should.be.false();
    mm.isMatch('z.js', '*.js').should.be.true();

    mm.isMatch('z.js', 'z*.js').should.be.true();
    mm.isMatch('a/z.js', 'a/z*.js').should.be.true();
    mm.isMatch('a/z.js', '*/z*.js').should.be.true();
  });

  it('should match globstars:', function() {
    mm.isMatch('a/b/c/z.js', '**/*.js').should.be.true();
    mm.isMatch('a/b/z.js', '**/*.js').should.be.true();
    mm.isMatch('a/z.js', '**/*.js').should.be.true();
    mm.isMatch('z.js', '**/*.js').should.be.true();
    mm.isMatch('z.js', '**/z*').should.be.true();

    mm.isMatch('a/b/c/d/e/z.js', 'a/b/**/*.js').should.be.true();
    mm.isMatch('a/b/c/d/z.js', 'a/b/**/*.js').should.be.true();
    mm.isMatch('a/b/c/z.js', 'a/b/c/**/*.js').should.be.true();
    mm.isMatch('a/b/c/z.js', 'a/b/c**/*.js').should.be.true();
    mm.isMatch('a/b/c/z.js', 'a/b/**/*.js').should.be.true();
    mm.isMatch('a/b/z.js', 'a/b/**/*.js').should.be.true();

    mm.isMatch('a/z.js', 'a/b/**/*.js').should.be.false();
    mm.isMatch('z.js', 'a/b/**/*.js').should.be.false();

    // issue #23
    mm.isMatch('zzjs', 'z*.js').should.be.false();
    mm.isMatch('zzjs', '*z.js').should.be.false();

    // issue #24
    mm.isMatch('a', '**').should.be.true();
    mm.isMatch('a', 'a/**').should.be.false();
    mm.isMatch('a/', '**').should.be.true();
    mm.isMatch('a/b/c/d', '**').should.be.true();
    mm.isMatch('a/b/c/d/', '**').should.be.true();
    mm.isMatch('a/b/c/d/', '**/**').should.be.true();
    mm.isMatch('a/b/c/d/', '**/b/**').should.be.true();
    mm.isMatch('a/b/c/d/', 'a/b/**').should.be.true();
    mm.isMatch('a/b/c/d/', 'a/b/**/').should.be.true();
    mm.isMatch('a/b/c/d/', 'a/b/**/c/**/').should.be.true();
    mm.isMatch('a/b/c/d/', 'a/b/**/c/**/d/').should.be.true();
    mm.isMatch('a/b/c/d/', 'a/b/**/f').should.be.false();
    mm.isMatch('a/b/c/d/e.f', 'a/b/**/**/*.*').should.be.true();
    mm.isMatch('a/b/c/d/e.f', 'a/b/**/*.*').should.be.true();
    mm.isMatch('a/b/c/d/e.f', 'a/b/**/c/**/d/*.*').should.be.true();
    mm.isMatch('a/b/c/d/e.f', 'a/b/**/d/**/*.*').should.be.true();
    mm.isMatch('a/b/c/d/g/e.f', 'a/b/**/d/**/*.*').should.be.true();
    mm.isMatch('a/b/c/d/g/g/e.f', 'a/b/**/d/**/*.*').should.be.true();

    // issue #15
    mm.isMatch('z.js', '**/z*.js').should.be.true();
    mm.isMatch('a/b-c/z.js', 'a/b-*/**/z.js').should.be.true();
    mm.isMatch('a/b-c/d/e/z.js', 'a/b-*/**/z.js').should.be.true();
  });

  /**
   * 1. micromatch differs from spec
   * 2. minimatch differs from spec
   * 3. both micromatch and minimatch differ from spec
   */

  it('Extended slash-matching features', function() {
    mm.isMatch('foo/baz/bar', 'foo*bar').should.be.false();
    mm.isMatch('foo/baz/bar', 'foo**bar').should.be.false();
    mm.isMatch('foobazbar', 'foo**bar').should.be.true(); // 3
    mm.isMatch('foo/baz/bar', 'foo/**/bar').should.be.true();
    mm.isMatch('foo/baz/bar', 'foo/**/**/bar').should.be.true();
    mm.isMatch('foo/b/a/z/bar', 'foo/**/bar').should.be.true();
    mm.isMatch('foo/b/a/z/bar', 'foo/**/**/bar').should.be.true();
    mm.isMatch('foo/bar', 'foo/**/bar').should.be.true();
    mm.isMatch('foo/bar', 'foo/**/**/bar').should.be.true();
    mm.isMatch('foo/bar', 'foo?bar').should.be.false();
    mm.isMatch('foo/bar', 'foo[/]bar').should.be.true(); // 2
    mm.isMatch('foo/bar', 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r').should.be.false();
    mm.isMatch('foo-bar', 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r').should.be.true();
    mm.isMatch('foo', '**/foo').should.be.true();
    mm.isMatch('foo', 'foo/**').should.be.false();
    mm.isMatch('XXX/foo', '**/foo').should.be.true();
    mm.isMatch('bar/baz/foo', '**/foo').should.be.true();
    mm.isMatch('bar/baz/foo', '*/foo').should.be.false();
    mm.isMatch('foo/bar/baz', '**/bar*').should.be.false();
    mm.isMatch('deep/foo/bar/baz', '**/bar/*').should.be.true();
    mm.isMatch('deep/foo/bar/baz/', '**/bar/*').should.be.false();
    mm.isMatch('deep/foo/bar/baz/', '**/bar/**').should.be.true();
    mm.isMatch('deep/foo/bar', '**/bar/*').should.be.false();
    mm.isMatch('deep/foo/bar/', '**/bar/**').should.be.true();
    mm.isMatch('foo/bar/baz', '**/bar**').should.be.false();
    mm.isMatch('foo/bar/baz/x', '*/bar/**').should.be.true();
    mm.isMatch('deep/foo/bar/baz/x', '*/bar/**').should.be.false();
    mm.isMatch('deep/foo/bar/baz/x', '**/bar/*/*').should.be.true();
    mm.isMatch('a/j/z/x.md', 'a/**/j/**/z/*.md').should.be.true();
    mm.isMatch('a/b/j/c/z/x.md', 'a/**/j/**/z/*.md').should.be.true();
  });

  it('question marks should not match slashes:', function() {
    mm.isMatch('aaa/bbb', 'aaa?bbb').should.be.false();
  });

  it('should not match dotfiles when `dot` or `dotfiles` are not set:', function() {
    mm.isMatch('.c.md', '*.md').should.be.false();
    mm.isMatch('a/.c.md', '*.md').should.be.false();
    mm.isMatch('a/.c.md', 'a/.c.md').should.be.true();
    mm.isMatch('.a', '*.md').should.be.false();
    mm.isMatch('.verb.txt', '*.md').should.be.false();
    mm.isMatch('a/b/c/.xyz.md', 'a/b/c/.*.md').should.be.true();
    mm.isMatch('.md', '.md').should.be.true();
    mm.isMatch('.txt', '.md').should.be.false();
    mm.isMatch('.md', '.md').should.be.true();
    mm.isMatch('.a', '.a').should.be.true();
    mm.isMatch('.b', '.b*').should.be.true();
    mm.isMatch('.ab', '.a*').should.be.true();
    mm.isMatch('.ab', '.*').should.be.true();
    mm.isMatch('.ab', '*.*').should.be.false();
    mm.isMatch('.md', 'a/b/c/*.md').should.be.false();
    mm.isMatch('.a.md', 'a/b/c/*.md').should.be.false();
    mm.isMatch('a/b/c/d.a.md', 'a/b/c/*.md').should.be.true();
    mm.isMatch('a/b/d/.md', 'a/b/c/*.md').should.be.false();
  });

  it('should match dotfiles when `dot` or `dotfiles` is set:', function() {
    mm.isMatch('.c.md', '*.md', {dot: true}).should.be.true();
    mm.isMatch('.c.md', '.*', {dot: true}).should.be.true();
    mm.isMatch('a/b/c/.xyz.md', 'a/b/c/*.md', {dot: true}).should.be.true();
    mm.isMatch('a/b/c/.xyz.md', 'a/b/c/.*.md', {dot: true}).should.be.true();
  });

  it('should match file paths:', function() {
    mm.isMatch('a/b/c/xyz.md', 'a/b/c/*.md').should.be.true();
    mm.isMatch('a/bb/c/xyz.md', 'a/*/c/*.md').should.be.true();
    mm.isMatch('a/bbbb/c/xyz.md', 'a/*/c/*.md').should.be.true();
    mm.isMatch('a/bb.bb/c/xyz.md', 'a/*/c/*.md').should.be.true();
    mm.isMatch('a/bb.bb/aa/bb/aa/c/xyz.md', 'a/**/c/*.md').should.be.true();
    mm.isMatch('a/bb.bb/aa/b.b/aa/c/xyz.md', 'a/**/c/*.md').should.be.true();
  });

  it('should match full file paths:', function() {
    mm.isMatch('a/.b', 'a/**/z/*.md').should.be.false();
    mm.isMatch('a/.b', 'a/.*').should.be.true();
    mm.isMatch('a/b/z/.a', 'a/**/z/*.a').should.be.false();
    mm.isMatch('a/b/z/.a', 'a/*/z/*.a').should.be.false();
    mm.isMatch('a/b/z/.a', 'a/*/z/.a').should.be.true();
    mm.isMatch('a/b/c/d/e/z/c.md', 'a/**/z/*.md').should.be.true();
    mm.isMatch('a/b/c/d/e/j/n/p/o/z/c.md', 'a/**/j/**/z/*.md').should.be.true();
    mm.isMatch('a/b/c/j/e/z/c.txt', 'a/**/j/**/z/*.md').should.be.false();
    mm.isMatch('a/b/d/xyz.md', 'a/b/**/c{d,e}/**/xyz.md').should.be.false();
    mm.isMatch('a/b/c/xyz.md', 'a/b/**/c{d,e}/**/xyz.md').should.be.false();
    mm.isMatch('a/b/c/cd/bar/xyz.md', 'a/b/**/c{d,e}/**/xyz.md').should.be.true();
    mm.isMatch('a/b/baz/ce/fez/xyz.md', 'a/b/**/c{d,e}/**/xyz.md').should.be.true();
  });

  it('should match paths with leading `./`:', function() {
    mm.isMatch('./.a', 'a/**/z/*.md').should.be.false();
    mm.isMatch('./a/b/z/.a', 'a/**/z/.a').should.be.false();
    mm.isMatch('./a/b/z/.a', './a/**/z/.a').should.be.true();
    mm.isMatch('./a/b/c/d/e/z/c.md', 'a/**/z/*.md').should.be.false();
    mm.isMatch('./a/b/c/d/e/z/c.md', './a/**/z/*.md').should.be.true();
    mm.isMatch('./a/b/c/d/e/z/c.md', './a/**/j/**/z/*.md').should.be.false();
    mm.isMatch('./a/b/c/j/e/z/c.md', './a/**/j/**/z/*.md').should.be.true();
    mm.isMatch('./a/b/c/j/e/z/c.md', 'a/**/j/**/z/*.md').should.be.false();
    mm.isMatch('./a/b/c/d/e/j/n/p/o/z/c.md', './a/**/j/**/z/*.md').should.be.true();
    mm.isMatch('./a/b/c/j/e/z/c.txt', './a/**/j/**/z/*.md').should.be.false();
    mm.isMatch('./a/b/d/xyz.md', './a/b/**/c{d,e}/**/xyz.md').should.be.false();
    mm.isMatch('./a/b/c/xyz.md', './a/b/**/c{d,e}/**/xyz.md').should.be.false();
    mm.isMatch('./a/b/c/cd/bar/xyz.md', './a/b/**/c{d,e}/**/xyz.md').should.be.true();
    mm.isMatch('./a/b/baz/ce/fez/xyz.md', './a/b/**/c{d,e}/**/xyz.md').should.be.true();
  });
});
