'use strict';

module.exports = args;

var debug = require('debug')('clite');
var abbrev = require('abbrev');
var getSettings = require('./settings');
var yargslib = require('yargs');
var defaultsDeep = require('lodash.defaultsdeep');

function args(argv, config) {
  var settings = getSettings(config);
  if (!Array.isArray(argv)) {
    throw new Error('process.argv type expected');
  }

  var aliases = Object.keys(settings.alias);
  var all = settings.options.concat(settings.booleans).concat(Object.keys(settings.commands)).concat(aliases);

  var aliasShortcuts = abbrev(aliases);

  // fixes up any issues
  settings.options.forEach(function (t) {
    return delete settings.alias[t];
  });
  debug('config', config);

  if (!settings.yargs) {
    settings.yargs = {};
    settings.options.forEach(function (cmd) {
      settings.yargs[cmd] = {
        describe: cmd
      };
    });

    settings.booleans.forEach(function (cmd) {
      settings.yargs[cmd] = {
        type: 'boolean',
        describe: cmd
      };
    });
  }

  defaultsDeep(settings.alias, abbrev(all));

  // set abbreviated aliases to have the value of the alias
  Object.keys(aliasShortcuts).forEach(function (a) {
    settings.alias[a] = settings.alias[aliasShortcuts[a]];
  });

  // total hack to capture the yargs help output
  var res = yargslib.reset().options(settings.yargs);
  var help = '';
  var old = console.log;
  console.log = function (s) {
    help = s;
  };
  res.showHelp('log');
  console.log = old;

  var yargs = yargslib.reset().options(settings.yargs).alias(settings.alias);
  var args = yargs.parse(argv);

  args.argv = args._.slice(0);
  args._.splice(0, 2); // now remove the `node` + script name

  debug('args', args);

  var override = false;

  if (args.help) {
    override = 'help';
    if (args._.length) {
      args.help = args._.pop();
    }
  }

  if (args.version) {
    override = 'version';
  }

  args.$_ = settings.commands[override || args._[0]] || // override or real
  settings.commands[settings.alias[args._[0]]] || // alias
  settings.commands._; // default

  // if there's no command config, then try to let the command match the
  // file system
  var userCommands = Object.keys((config || {}).commands || []).length;
  if (!args.$_ && args._.length && userCommands === 0) {
    args.$_ = args._.shift();
  }

  // if our command was used off the CLI arg, then let's remove it from the
  // command args
  if (args.$_ === settings.commands[args._[0]]) {
    args._.shift();
  }

  return {
    help: help,
    args: args
  };
}