// Generated by CoffeeScript 1.3.3
(function() {
  var GIT_SYNTAX, assert, dreamopt, o, oo, ooo,
    __hasProp = {}.hasOwnProperty;

  assert = require('assert');

  dreamopt = require('../lib/dreamopt');

  GIT_SYNTAX = ["  remote", ["Manage set of tracked repositories.", "  add", ["Adds a remote named <name> for the repository at <url>.", "Usage: git remote add <name> <url>", "  <name>  name of remote ref", "  <url>  repository url"], "  rename", ["Rename the remote named <old> to <new>.", "Usage: git remote rename <old> <new>", "  <old>  old remote ref name", "  <new>  new remote ref name"], "  rm", ["Remove the remote named <name>.", "Usage: git remote rm <name>", "  <name>  remote ref name"]], "  push", ["Update remote refs along with associated objects.", "Usage: git push <repository> <refspec>", "  <repository>  The 'remote' repository that is destination of a push operation.", "  <refspec>  Used to specify with what <src> object the <dst> ref is to be updated."], "Global options:"];

  o = function(syntax, argv, expected) {
    expected.argv || (expected.argv = []);
    return describe("when given " + (JSON.stringify(argv)), function() {
      var k, v, _actual, _fn;
      _actual = null;
      before(function() {
        return _actual = dreamopt(syntax, {
          argv: argv,
          error: function(e) {
            throw e;
          }
        });
      });
      _fn = function(k, v) {
        return it("value of " + k + " should be " + (JSON.stringify(v)), function() {
          return assert.deepEqual(_actual[k], v, "" + k + " is " + (JSON.stringify(_actual[k])) + ", expected " + (JSON.stringify(v)) + ", actual = " + (JSON.stringify(_actual)));
        });
      };
      for (k in expected) {
        if (!__hasProp.call(expected, k)) continue;
        v = expected[k];
        _fn(k, v);
      }
      return it("should not return any other option keys", function() {
        var keys;
        keys = {};
        for (k in _actual) {
          if (!__hasProp.call(_actual, k)) continue;
          v = _actual[k];
          keys[k] = true;
        }
        for (k in expected) {
          if (!__hasProp.call(expected, k)) continue;
          v = expected[k];
          delete keys[k];
        }
        return assert.deepEqual(keys, [], "Extra keys found in expected: " + (Object.keys(keys).join(', ')) + ", actual = " + (JSON.stringify(_actual)) + ", expected = " + (JSON.stringify(expected)));
      });
    });
  };

  oo = function(syntax, argv, errorRegexp) {
    return describe("when given " + (JSON.stringify(argv)), function() {
      var _actual, _err;
      _actual = null;
      _err = null;
      before(function() {
        try {
          return _actual = dreamopt(syntax, {
            argv: argv,
            error: function(e) {
              throw e;
            }
          });
        } catch (e) {
          return _err = e;
        }
      });
      return it("should throw an error matching " + errorRegexp, function() {
        assert.ok(!!_err, "Expected error matching " + errorRegexp + ", no error thrown, actual = " + (JSON.stringify(_actual)));
        return assert.ok(_err.message.match(errorRegexp), "Expected error matching " + errorRegexp + ", got error " + _err.message);
      });
    });
  };

  ooo = function(syntax, expectedUsage, argv) {
    var doit;
    if (argv == null) {
      argv = [];
    }
    doit = function() {
      return it("should display correct usage info", function() {
        var captureUsage, _usage;
        _usage = null;
        captureUsage = function(usage) {
          _usage = usage;
          throw new Error("bail out of captureUsage");
        };
        try {
          dreamopt(syntax, {
            argv: argv.concat(['--help']),
            help: captureUsage,
            error: function(e) {
              throw e;
            }
          });
        } catch (e) {
          if (e.message !== "bail out of captureUsage") {
            throw e;
          }
        }
        return assert.equal(_usage.trim(), expectedUsage.trim(), "Usage mismatch, actual:\n" + (_usage.trim()) + "\n\nExpected:\n" + (expectedUsage.trim()) + "\n");
      });
    };
    if (argv.length > 0) {
      return describe("when given " + (argv.concat(['--help']).join(' ')), doit);
    } else {
      return doit();
    }
  };

  describe('dreamopt', function() {
    describe("with a syntax as simple as -a/--AAA, -b/--BBB COUNT, -c/--ccc", function() {
      var syntax;
      syntax = ["  -a, --AAA  Simple option", "  -b, --BBB COUNT  Option with value", "  -c, --[no-]ccc  Flag option", "  -d, --ddd <value>  Another option with value"];
      o(syntax, [''], {});
      o(syntax, ['-a'], {
        AAA: true
      });
      o(syntax, ['-b', '10'], {
        BBB: 10
      });
      o(syntax, ['-b10'], {
        BBB: 10
      });
      o(syntax, ['-ac'], {
        AAA: true,
        ccc: true
      });
      o(syntax, ['-ab', '10'], {
        AAA: true,
        BBB: 10
      });
      o(syntax, ['-ab10'], {
        AAA: true,
        BBB: 10
      });
      oo(syntax, ['-z'], /Unknown short option/);
      oo(syntax, ['-azc'], /Unknown short option/);
      oo(syntax, ['-b'], /requires an argument/);
      oo(syntax, ['-ab'], /requires an argument/);
      oo(syntax, ['-a', '-b'], /requires an argument/);
      o(syntax, ['--AAA'], {
        AAA: true
      });
      o(syntax, ['--no-AAA'], {
        AAA: false
      });
      o(syntax, ['--ccc'], {
        ccc: true
      });
      o(syntax, ['--no-ccc'], {
        ccc: false
      });
      o(syntax, ['--BBB', '10'], {
        BBB: 10
      });
      o(syntax, ['--BBB=10'], {
        BBB: 10
      });
      oo(syntax, ['--zzz'], /Unknown long option/);
      oo(syntax, ['--BBB'], /requires an argument/);
      return ooo(syntax, "Options:\n  -a, --AAA             Simple option\n  -b, --BBB COUNT       Option with value\n  -c, --[no-]ccc        Flag option\n  -d, --ddd <value>     Another option with value\n  -h, --help            Display this usage information");
    });
    describe("with a syntax that has two positional arguments and one option (-v/--verbose)", function() {
      var syntax;
      syntax = ["  -v, --verbose  Be verbose", "  <first>  First positional arg", "  <second>  Second positional arg"];
      o(syntax, [], {});
      o(syntax, ['-v'], {
        verbose: true
      });
      o(syntax, ['foo'], {
        argv: ['foo'],
        first: 'foo'
      });
      o(syntax, ['foo', 'bar'], {
        argv: ['foo', 'bar'],
        first: 'foo',
        second: 'bar'
      });
      o(syntax, ['-v', 'foo'], {
        argv: ['foo'],
        first: 'foo',
        verbose: true
      });
      o(syntax, ['foo', '-v'], {
        argv: ['foo'],
        first: 'foo',
        verbose: true
      });
      return o(syntax, ['-v', 'foo', 'bar'], {
        argv: ['foo', 'bar'],
        first: 'foo',
        second: 'bar',
        verbose: true
      });
    });
    describe("with a syntax that has two positional arguments, both of which have default values", function() {
      var syntax;
      syntax = ["  FIRST  First positional arg (default: 10)", "  SECOND  Second positional arg (default: 20)"];
      o(syntax, [], {
        argv: [10, 20],
        first: 10,
        second: 20
      });
      o(syntax, ['foo'], {
        argv: ['foo', 20],
        first: 'foo',
        second: 20
      });
      return o(syntax, ['foo', 'bar'], {
        argv: ['foo', 'bar'],
        first: 'foo',
        second: 'bar'
      });
    });
    describe("with a syntax that has two positional arguments, one of which is required", function() {
      var syntax;
      syntax = ["  <first>  First positional arg  #required", "  <second>  Second positional arg (default: 20)"];
      oo(syntax, [], /required/);
      o(syntax, ['foo'], {
        argv: ['foo', 20],
        first: 'foo',
        second: 20
      });
      return o(syntax, ['foo', 'bar'], {
        argv: ['foo', 'bar'],
        first: 'foo',
        second: 'bar'
      });
    });
    describe("with a syntax that has a required option", function() {
      var syntax;
      syntax = ["  --src FILE  Source file  #required", "  <first>  First positional arg"];
      oo(syntax, [], /required/);
      oo(syntax, ['foo'], /required/);
      oo(syntax, ['--src'], /requires an argument/);
      o(syntax, ['--src', 'xxx'], {
        src: 'xxx'
      });
      o(syntax, ['--src', 'xxx', 'zzz'], {
        src: 'xxx',
        first: 'zzz',
        argv: ['zzz']
      });
      return o(syntax, ['zzz', '--src', 'xxx'], {
        src: 'xxx',
        first: 'zzz',
        argv: ['zzz']
      });
    });
    describe("with a syntax that has a list option", function() {
      var syntax;
      syntax = ["  --src FILE  Source file  #list"];
      o(syntax, [], {
        src: [],
        argv: []
      });
      o(syntax, ['--src', 'xxx'], {
        src: ['xxx'],
        argv: []
      });
      return o(syntax, ['--src', 'xxx', '--src', 'yyy'], {
        src: ['xxx', 'yyy'],
        argv: []
      });
    });
    describe("with a syntax that has two subcommands", function() {
      var barHandler, syntax;
      barHandler = function(result) {
        return result.bbbar = 42;
      };
      syntax = ["  foo  Do something", [], "  bar  Do something else", barHandler, []];
      oo(syntax, [], /no command specified/i);
      o(syntax, ['foo'], {
        argv: [],
        command: 'foo'
      });
      return o(syntax, ['bar'], {
        argv: [],
        command: 'bar',
        bbbar: 42
      });
    });
    describe("with a syntax that has a subcommand with local options", function() {
      var syntax;
      syntax = ["  foo  Do something", [], "  bar  Do something else", ["  --boz  Enable boz"], "  -v, --verbose  Verbose"];
      oo(syntax, [], /no command specified/i);
      o(syntax, ['foo'], {
        argv: [],
        command: 'foo'
      });
      o(syntax, ['-v', 'foo'], {
        argv: [],
        command: 'foo',
        verbose: true
      });
      o(syntax, ['foo', '-v'], {
        argv: [],
        command: 'foo',
        verbose: true
      });
      oo(syntax, ['foo', '--boz'], /unknown long option/i);
      o(syntax, ['bar'], {
        argv: [],
        command: 'bar'
      });
      o(syntax, ['bar', '--boz'], {
        argv: [],
        command: 'bar',
        boz: true
      });
      o(syntax, ['-v', 'bar', '--boz'], {
        argv: [],
        command: 'bar',
        boz: true,
        verbose: true
      });
      return o(syntax, ['bar', '--boz', '-v'], {
        argv: [],
        command: 'bar',
        boz: true,
        verbose: true
      });
    });
    return describe("with a git-style syntax", function() {
      oo(GIT_SYNTAX, [], /no command specified/i);
      o(GIT_SYNTAX, ['push'], {
        argv: [],
        command: 'push'
      });
      ooo(GIT_SYNTAX, "Commands:\n  remote                Manage set of tracked repositories.\n  push                  Update remote refs along with associated objects.\n\nGlobal options:\n  -h, --help            Display this usage information");
      ooo(GIT_SYNTAX, "Update remote refs along with associated objects.\n\nUsage: git push <repository> <refspec>\n\nArguments:\n  <repository>          The 'remote' repository that is destination of a push operation.\n  <refspec>             Used to specify with what <src> object the <dst> ref is to be updated.\n\nGlobal options:\n  -h, --help            Display this usage information", ['push']);
      ooo(GIT_SYNTAX, "Manage set of tracked repositories.\n\nCommands:\n  add                   Adds a remote named <name> for the repository at <url>.\n  rename                Rename the remote named <old> to <new>.\n  rm                    Remove the remote named <name>.\n\nGlobal options:\n  -h, --help            Display this usage information", ['remote']);
      return ooo(GIT_SYNTAX, "Adds a remote named <name> for the repository at <url>.\n\nUsage: git remote add <name> <url>\n\nArguments:\n  <name>                name of remote ref\n  <url>                 repository url\n\nGlobal options:\n  -h, --help            Display this usage information", ['remote', 'add']);
    });
  });

  setTimeout((function() {}), 2000);

}).call(this);
