var optionator, equal, q, qo;
optionator = require('../..');
equal = require('assert').strictEqual;
q = function(expected, options, args){
  var generateHelp, helpText, e;
  generateHelp = optionator(options).generateHelp;
  helpText = generateHelp(args);
  try {
    return equal(helpText, expected);
  } catch (e$) {
    e = e$;
    console.log('# Result:');
    console.log(helpText);
    console.log('# Expected:');
    console.log(expected);
    throw e;
  }
};
qo = function(expected, optionName, options){
  var generateHelpForOption, helpText, e;
  generateHelpForOption = optionator(options).generateHelpForOption;
  helpText = generateHelpForOption(optionName);
  try {
    return equal(helpText, expected);
  } catch (e$) {
    e = e$;
    console.log('# Result:');
    console.log(helpText);
    console.log('# Expected:');
    console.log(expected);
    throw e;
  }
};
describe('help', function(){
  var helpOption, countOption, objOption;
  helpOption = {
    option: 'help',
    type: 'Boolean',
    description: 'recieve help - print this info'
  };
  countOption = {
    option: 'count',
    type: 'Number',
    description: 'count of stuff that is to be counted'
  };
  objOption = {
    option: 'obj',
    type: '{x: Number, y: Boolean, z: Object}',
    description: 'an object full of things and stuff'
  };
  it('single basic option', function(){
    return q('  --help  recieve help - print this info', {
      options: [helpOption]
    });
  });
  it('prepend/append', function(){
    return q('cmd\n\n  --help  recieve help - print this info\n\nversion 0.1.0', {
      prepend: 'cmd',
      append: 'version 0.1.0',
      options: [helpOption]
    });
  });
  it('heading', function(){
    return q('Options:\n  --help  recieve help - print this info', {
      options: [
        {
          heading: 'Options'
        }, helpOption
      ]
    });
  });
  it('heading with prepend', function(){
    return q('cmd\n\nOptions:\n  --help  recieve help - print this info', {
      prepend: 'cmd',
      options: [
        {
          heading: 'Options'
        }, helpOption
      ]
    });
  });
  it('two options', function(){
    return q('  --help          recieve help - print this info\n  --count Number  count of stuff that is to be counted', {
      options: [helpOption, countOption]
    });
  });
  it('headings', function(){
    return q('Options:\n  --help          recieve help - print this info\n\nMore Options:\n  --count Number  count of stuff that is to be counted', {
      options: [
        {
          heading: 'Options'
        }, helpOption, {
          heading: 'More Options'
        }, countOption
      ]
    });
  });
  it('greatly differnt lengths', function(){
    return q('cmd\n\n  --help          recieve help - print this info\n  --count Number  count of stuff that is to be counted\n  --obj {x: Number, y: Boolean, z: Object}  an object full of things and stuff', {
      prepend: 'cmd',
      options: [helpOption, countOption, objOption]
    });
  });
  it('short main name', function(){
    return q('  -h  help me', {
      options: [{
        option: 'h',
        type: 'Boolean',
        description: 'help me'
      }]
    });
  });
  it('one alias', function(){
    return q('  -h, -H, --help  help me', {
      options: [{
        option: 'help',
        alias: ['h', 'H'],
        type: 'Boolean',
        description: 'help me'
      }]
    });
  });
  it('enum type', function(){
    return q('  --size String  shirt size - either: small, medium, or large', {
      options: [{
        option: 'size',
        type: 'String',
        'enum': ['small', 'medium', 'large'],
        description: 'shirt size'
      }]
    });
  });
  it('enum type, just two', function(){
    return q('  --size String  shirt size - either: small or large', {
      options: [{
        option: 'size',
        type: 'String',
        'enum': ['small', 'large'],
        description: 'shirt size'
      }]
    });
  });
  it('default', function(){
    return q('  --count Number  count of stuff that is to be counted - default: 2', {
      options: [{
        option: 'count',
        type: 'Number',
        description: 'count of stuff that is to be counted',
        'default': '2'
      }]
    });
  });
  it('default with no description', function(){
    return q('  --count Number  default: 2', {
      options: [{
        option: 'count',
        type: 'Number',
        'default': '2'
      }]
    });
  });
  it('default - boolean with true when no short alias', function(){
    return q('  --no-colour', {
      options: [{
        option: 'colour',
        type: 'Boolean',
        'default': 'true'
      }]
    });
  });
  it('default - boolean with true when no short alias but long aliases', function(){
    return q('  --no-colour, --no-color', {
      options: [{
        option: 'colour',
        type: 'Boolean',
        alias: 'color',
        'default': 'true'
      }]
    });
  });
  it('default - boolean with true with short alias', function(){
    return q('  -c, --colour  default: true', {
      options: [{
        option: 'colour',
        alias: 'c',
        type: 'Boolean',
        'default': 'true'
      }]
    });
  });
  it('many aliases', function(){
    return q('  -h, -H, --halp, --help  halp me', {
      options: [{
        option: 'halp',
        alias: ['help', 'h', 'H'],
        type: 'Boolean',
        description: 'halp me'
      }]
    });
  });
  it('aliases prop predefined', function(){
    return q('  -h, -H, --halp, --help  halp me', {
      options: [{
        option: 'halp',
        aliases: ['help', 'h', 'H'],
        type: 'Boolean',
        description: 'halp me'
      }]
    });
  });
  it('NUM', function(){
    return q('  -NUM::Int  the number', {
      options: [{
        option: 'NUM',
        type: 'Int',
        description: 'the number'
      }]
    });
  });
  it('show hidden', function(){
    var opts;
    opts = {
      options: [
        {
          option: 'hidden',
          type: 'Boolean',
          description: 'magic',
          hidden: true
        }, {
          option: 'visible',
          type: 'Boolean',
          description: 'boring'
        }
      ]
    };
    q('  --visible  boring', opts);
    return q('  --hidden   magic\n  --visible  boring', opts, {
      showHidden: true
    });
  });
  it('interpolation', function(){
    var opts;
    opts = {
      prepend: 'usage {{x}}',
      options: [{
        heading: 'Options'
      }],
      append: 'version {{version}}'
    };
    it('none', function(){
      return q('usage {{x}}\n\nOptions:\n\nversion {{version}}', opts);
    });
    it('partial', function(){
      return q('usage cmd\n\nOptions:\n\nversion {{version}}', opts, {
        interpolate: {
          x: 'cmd'
        }
      });
    });
    it('basic', function(){
      return q('usage cmd\n\nOptions:\n\nversion 2', opts, {
        interpolate: {
          x: 'cmd',
          version: 2
        }
      });
    });
    it('with empty string', function(){
      return q('usage \n\nOptions:\n\nversion ', opts, {
        interpolate: {
          x: '',
          version: ''
        }
      });
    });
    it('more than once, with number', function(){
      var opts;
      opts = {
        prepend: 'usage {{$0}}, {{$0}}',
        options: [{
          heading: 'Options'
        }],
        append: '{{$0}} and {{$0}}'
      };
      return q('usage xx, xx\n\nOptions:\n\nxx and xx', opts, {
        interpolate: {
          $0: 'xx'
        }
      });
    });
  });
  it('no stdout', function(){
    return q('cmd\n\n  --obj {x: Number, y: Boolean, z: Object}  an object full of things and stuff', {
      prepend: 'cmd',
      options: [objOption],
      stdout: null
    });
  });
  it('no description', function(){
    return q('cmd\n\n  --help', {
      prepend: 'cmd',
      options: [{
        option: 'help',
        type: 'Boolean'
      }]
    });
  });
  it('wrapping', function(){
    it('basic with max-width', function(){
      return q('cmd\n\n  --help  recieve help - print this info', {
        prepend: 'cmd',
        options: [helpOption],
        stdout: {
          isTTY: true,
          columns: 250
        }
      });
    });
    it('partial single', function(){
      return q('cmd\n\n  --obj {x: Number, y: Boolean, z: Object}  an object full of\n                                            things and stuff', {
        prepend: 'cmd',
        options: [objOption],
        stdout: {
          isTTY: true,
          columns: 68
        }
      });
    });
    it('full single', function(){
      return q('cmd\n\n  --obj {x: Number, y: Boolean, z: Object}\n      an object full of things and stuff', {
        prepend: 'cmd',
        options: [objOption],
        stdout: {
          isTTY: true,
          columns: 50
        }
      });
    });
    it('partial several', function(){
      return q('cmd\n\nOptions:\n  --help          recieve help - print this info\n  --count Number  count of stuff that is to be counted\n  --obj {x: Number, y: Boolean, z: Object}  an object full of things\n                                            and stuff', {
        prepend: 'cmd',
        options: [
          {
            heading: 'Options'
          }, helpOption, countOption, objOption
        ],
        stdout: {
          isTTY: true,
          columns: 70
        }
      });
    });
    it('full several', function(){
      return q('cmd\n\nOptions:\n  --help          recieve help - print this info\n  --count Number  count of stuff that is to be counted\n  --obj {x: Number, y: Boolean, z: Object}\n      an object full of things and stuff', {
        prepend: 'cmd',
        options: [
          {
            heading: 'Options'
          }, helpOption, countOption, objOption
        ],
        stdout: {
          isTTY: true,
          columns: 55
        }
      });
    });
    it('partial all', function(){
      return q('cmd\n\n  --help          recieve help - print this\n                  info\n  --count Number  count of stuff that is to\n                  be counted', {
        prepend: 'cmd',
        options: [helpOption, countOption],
        stdout: {
          isTTY: true,
          columns: 46
        }
      });
    });
    it('full all', function(){
      return q('cmd\n\n  --help\n      recieve help -\n      print this info\n  --count Number\n      count of stuff\n      that is to be\n      counted', {
        prepend: 'cmd',
        options: [helpOption, countOption],
        stdout: {
          isTTY: true,
          columns: 26
        }
      });
    });
    return it('type', function(){
      return q('cmd\n\n  --obj {x: Number, y:\n        Boolean, z: Object}\n      an object full of things\n      and stuff', {
        prepend: 'cmd',
        options: [objOption],
        stdout: {
          isTTY: true,
          columns: 32
        }
      });
    });
  });
  it('for option', function(){
    var opts;
    opts = {
      options: [
        {
          option: 'times-num',
          type: 'Number',
          description: 'times to do something.',
          example: '--times-num 23'
        }, {
          option: 'input',
          alias: 'i',
          type: 'OBJ::Object',
          description: 'the input that you want',
          example: '--input "x: 52, y: [1,2,3]"',
          'default': '{a: 1}'
        }, {
          option: 'nope',
          type: 'Boolean',
          description: 'nothing at all',
          longDescription: 'really nothing at all'
        }, {
          option: 'nope2',
          type: 'Boolean'
        }
      ]
    };
    it('times', function(){
      return qo('--times-num Number\n==================\ndescription: Times to do something.\nexample: --times-num 23', 'times-num', opts);
    });
    it('input', function(){
      qo('-i, --input OBJ::Object\n=======================\ndefault: {a: 1}\ndescription: The input that you want.\nexample: --input "x: 52, y: [1,2,3]"', 'input', opts);
      return qo('-i, --input OBJ::Object\n=======================\ndefault: {a: 1}\ndescription: The input that you want.\nexample: --input "x: 52, y: [1,2,3]"', 'i', opts);
    });
    it('no example - long description', function(){
      return qo('--nope\n======\ndescription: really nothing at all', 'nope', opts);
    });
    it('long description text with max width', function(){
      var opts;
      opts = {
        options: [{
          option: 'long',
          type: 'String',
          description: 'it goes on and on my friends, some people started singing it not knowing what it was'
        }],
        stdout: {
          isTTY: true,
          columns: 50
        }
      };
      qo('--long String\n=============\ndescription:\nIt goes on and on my friends, some people\nstarted singing it not knowing what it was.', 'long', opts);
      opts.stdout = null;
      return qo('--long String\n=============\ndescription: It goes on and on my friends, some people started singing it not knowing what it was.', 'long', opts);
    });
    it('multiple examples', function(){
      return qo('--op\n====\ndescription: The thing.\nexamples:\ncmd --op\ncmd --no-op', 'op', {
        options: [{
          option: 'op',
          type: 'Boolean',
          description: 'the thing',
          example: ['cmd --op', 'cmd --no-op']
        }]
      });
    });
    it('rest positional', function(){
      var opts;
      opts = {
        options: [{
          option: 'rest',
          type: 'Boolean',
          description: 'The rest',
          restPositional: true
        }],
        stdout: {
          isTTY: false
        }
      };
      qo('--rest\n======\ndescription: The rest. Everything after this option is considered a positional argument, even if it looks like an option.', 'rest', opts);
      delete opts.options[0].description;
      return qo('--rest\n======\ndescription: Everything after this option is considered a positional argument, even if it looks like an option.', 'rest', opts);
    });
    it('no description or rest positional', function(){
      return qo('--nope2', 'nope2', opts);
    });
    return it('invalid option', function(){
      return qo("Invalid option '--FAKE' - perhaps you meant '-i'?", 'FAKE', opts);
    });
  });
  it('help style settings', function(){
    it('all different', function(){
      var opts;
      opts = {
        helpStyle: {
          aliasSeparator: '|',
          typeSeparator: ': ',
          descriptionSeparator: ' > ',
          initialIndent: 1,
          secondaryIndent: 2,
          maxPadFactor: 10
        },
        prepend: 'cmd',
        options: [
          {
            option: 'help',
            alias: 'h',
            type: 'Boolean',
            description: 'recieve help - print this info'
          }, countOption, objOption
        ]
      };
      return q('cmd\n\n -h|--help                                 > recieve help - print this info\n --count: Number                           > count of stuff that is to be counted\n --obj: {x: Number, y: Boolean, z: Object} > an object full of things and stuff', opts);
    });
  });
});
