'use strict'

const inspect = require('util').inspect
const isPromise = require('./is-promise')
const { applyMiddleware, commandMiddlewareFactory } = require('./middleware')
const path = require('path')
const Parser = require('yargs-parser')

const DEFAULT_MARKER = /(^\*)|(^\$0)/

// handles parsing positional arguments,
// and populating argv with said positional
// arguments.
module.exports = function command (yargs, usage, validation, globalMiddleware) {
  const self = {}
  let handlers = {}
  let aliasMap = {}
  let defaultCommand
  globalMiddleware = globalMiddleware || []

  self.addHandler = function addHandler (cmd, description, builder, handler, commandMiddleware) {
    let aliases = []
    const middlewares = commandMiddlewareFactory(commandMiddleware)
    handler = handler || (() => {})

    if (Array.isArray(cmd)) {
      aliases = cmd.slice(1)
      cmd = cmd[0]
    } else if (typeof cmd === 'object') {
      let command = (Array.isArray(cmd.command) || typeof cmd.command === 'string') ? cmd.command : moduleName(cmd)
      if (cmd.aliases) command = [].concat(command).concat(cmd.aliases)
      self.addHandler(command, extractDesc(cmd), cmd.builder, cmd.handler, cmd.middlewares)
      return
    }

    // allow a module to be provided instead of separate builder and handler
    if (typeof builder === 'object' && builder.builder && typeof builder.handler === 'function') {
      self.addHandler([cmd].concat(aliases), description, builder.builder, builder.handler, builder.middlewares)
      return
    }

    // parse positionals out of cmd string
    const parsedCommand = self.parseCommand(cmd)

    // remove positional args from aliases only
    aliases = aliases.map(alias => self.parseCommand(alias).cmd)

    // check for default and filter out '*''
    let isDefault = false
    const parsedAliases = [parsedCommand.cmd].concat(aliases).filter((c) => {
      if (DEFAULT_MARKER.test(c)) {
        isDefault = true
        return false
      }
      return true
    })

    // standardize on $0 for default command.
    if (parsedAliases.length === 0 && isDefault) parsedAliases.push('$0')

    // shift cmd and aliases after filtering out '*'
    if (isDefault) {
      parsedCommand.cmd = parsedAliases[0]
      aliases = parsedAliases.slice(1)
      cmd = cmd.replace(DEFAULT_MARKER, parsedCommand.cmd)
    }

    // populate aliasMap
    aliases.forEach((alias) => {
      aliasMap[alias] = parsedCommand.cmd
    })

    if (description !== false) {
      usage.command(cmd, description, isDefault, aliases)
    }

    handlers[parsedCommand.cmd] = {
      original: cmd,
      description: description,
      handler,
      builder: builder || {},
      middlewares,
      demanded: parsedCommand.demanded,
      optional: parsedCommand.optional
    }

    if (isDefault) defaultCommand = handlers[parsedCommand.cmd]
  }

  self.addDirectory = function addDirectory (dir, context, req, callerFile, opts) {
    opts = opts || {}
    // disable recursion to support nested directories of subcommands
    if (typeof opts.recurse !== 'boolean') opts.recurse = false
    // exclude 'json', 'coffee' from require-directory defaults
    if (!Array.isArray(opts.extensions)) opts.extensions = ['js']
    // allow consumer to define their own visitor function
    const parentVisit = typeof opts.visit === 'function' ? opts.visit : o => o
    // call addHandler via visitor function
    opts.visit = function visit (obj, joined, filename) {
      const visited = parentVisit(obj, joined, filename)
      // allow consumer to skip modules with their own visitor
      if (visited) {
        // check for cyclic reference
        // each command file path should only be seen once per execution
        if (~context.files.indexOf(joined)) return visited
        // keep track of visited files in context.files
        context.files.push(joined)
        self.addHandler(visited)
      }
      return visited
    }
    require('require-directory')({ require: req, filename: callerFile }, dir, opts)
  }

  // lookup module object from require()d command and derive name
  // if module was not require()d and no name given, throw error
  function moduleName (obj) {
    const mod = require('which-module')(obj)
    if (!mod) throw new Error(`No command name given for module: ${inspect(obj)}`)
    return commandFromFilename(mod.filename)
  }

  // derive command name from filename
  function commandFromFilename (filename) {
    return path.basename(filename, path.extname(filename))
  }

  function extractDesc (obj) {
    for (let keys = ['describe', 'description', 'desc'], i = 0, l = keys.length, test; i < l; i++) {
      test = obj[keys[i]]
      if (typeof test === 'string' || typeof test === 'boolean') return test
    }
    return false
  }

  self.parseCommand = function parseCommand (cmd) {
    const extraSpacesStrippedCommand = cmd.replace(/\s{2,}/g, ' ')
    const splitCommand = extraSpacesStrippedCommand.split(/\s+(?![^[]*]|[^<]*>)/)
    const bregex = /\.*[\][<>]/g
    const parsedCommand = {
      cmd: (splitCommand.shift()).replace(bregex, ''),
      demanded: [],
      optional: []
    }
    splitCommand.forEach((cmd, i) => {
      let variadic = false
      cmd = cmd.replace(/\s/g, '')
      if (/\.+[\]>]/.test(cmd) && i === splitCommand.length - 1) variadic = true
      if (/^\[/.test(cmd)) {
        parsedCommand.optional.push({
          cmd: cmd.replace(bregex, '').split('|'),
          variadic
        })
      } else {
        parsedCommand.demanded.push({
          cmd: cmd.replace(bregex, '').split('|'),
          variadic
        })
      }
    })
    return parsedCommand
  }

  self.getCommands = () => Object.keys(handlers).concat(Object.keys(aliasMap))

  self.getCommandHandlers = () => handlers

  self.hasDefaultCommand = () => !!defaultCommand

  self.runCommand = function runCommand (command, yargs, parsed, commandIndex) {
    let aliases = parsed.aliases
    const commandHandler = handlers[command] || handlers[aliasMap[command]] || defaultCommand
    const currentContext = yargs.getContext()
    let numFiles = currentContext.files.length
    const parentCommands = currentContext.commands.slice()

    // what does yargs look like after the builder is run?
    let innerArgv = parsed.argv
    let innerYargs = null
    let positionalMap = {}
    if (command) {
      currentContext.commands.push(command)
      currentContext.fullCommands.push(commandHandler.original)
    }
    if (typeof commandHandler.builder === 'function') {
      // a function can be provided, which builds
      // up a yargs chain and possibly returns it.
      innerYargs = commandHandler.builder(yargs.reset(parsed.aliases))
      if (!innerYargs || (typeof innerYargs._parseArgs !== 'function')) {
        innerYargs = yargs
      }
      if (shouldUpdateUsage(innerYargs)) {
        innerYargs.getUsageInstance().usage(
          usageFromParentCommandsCommandHandler(parentCommands, commandHandler),
          commandHandler.description
        )
      }
      innerArgv = innerYargs._parseArgs(null, null, true, commandIndex)
      aliases = innerYargs.parsed.aliases
    } else if (typeof commandHandler.builder === 'object') {
      // as a short hand, an object can instead be provided, specifying
      // the options that a command takes.
      innerYargs = yargs.reset(parsed.aliases)
      if (shouldUpdateUsage(innerYargs)) {
        innerYargs.getUsageInstance().usage(
          usageFromParentCommandsCommandHandler(parentCommands, commandHandler),
          commandHandler.description
        )
      }
      Object.keys(commandHandler.builder).forEach((key) => {
        innerYargs.option(key, commandHandler.builder[key])
      })
      innerArgv = innerYargs._parseArgs(null, null, true, commandIndex)
      aliases = innerYargs.parsed.aliases
    }

    if (!yargs._hasOutput()) {
      positionalMap = populatePositionals(commandHandler, innerArgv, currentContext, yargs)
    }

    const middlewares = globalMiddleware.slice(0).concat(commandHandler.middlewares)
    applyMiddleware(innerArgv, yargs, middlewares, true)

    // we apply validation post-hoc, so that custom
    // checks get passed populated positional arguments.
    if (!yargs._hasOutput()) yargs._runValidation(innerArgv, aliases, positionalMap, yargs.parsed.error)

    if (commandHandler.handler && !yargs._hasOutput()) {
      yargs._setHasOutput()
      // to simplify the parsing of positionals in commands,
      // we temporarily populate '--' rather than _, with arguments
      const populateDoubleDash = !!yargs.getOptions().configuration['populate--']
      if (!populateDoubleDash) yargs._copyDoubleDash(innerArgv)

      innerArgv = applyMiddleware(innerArgv, yargs, middlewares, false)
      let handlerResult
      if (isPromise(innerArgv)) {
        handlerResult = innerArgv.then(argv => commandHandler.handler(argv))
      } else {
        handlerResult = commandHandler.handler(innerArgv)
      }

      if (isPromise(handlerResult)) {
        yargs.getUsageInstance().cacheHelpMessage()
        handlerResult.catch(error => {
          try {
            yargs.getUsageInstance().fail(null, error)
          } catch (err) {
            // fail's throwing would cause an unhandled rejection.
          }
        })
      }
    }

    if (command) {
      currentContext.commands.pop()
      currentContext.fullCommands.pop()
    }
    numFiles = currentContext.files.length - numFiles
    if (numFiles > 0) currentContext.files.splice(numFiles * -1, numFiles)

    return innerArgv
  }

  function shouldUpdateUsage (yargs) {
    return !yargs.getUsageInstance().getUsageDisabled() &&
      yargs.getUsageInstance().getUsage().length === 0
  }

  function usageFromParentCommandsCommandHandler (parentCommands, commandHandler) {
    const c = DEFAULT_MARKER.test(commandHandler.original) ? commandHandler.original.replace(DEFAULT_MARKER, '').trim() : commandHandler.original
    const pc = parentCommands.filter((c) => { return !DEFAULT_MARKER.test(c) })
    pc.push(c)
    return `$0 ${pc.join(' ')}`
  }

  self.runDefaultBuilderOn = function (yargs) {
    if (shouldUpdateUsage(yargs)) {
      // build the root-level command string from the default string.
      const commandString = DEFAULT_MARKER.test(defaultCommand.original)
        ? defaultCommand.original : defaultCommand.original.replace(/^[^[\]<>]*/, '$0 ')
      yargs.getUsageInstance().usage(
        commandString,
        defaultCommand.description
      )
    }
    const builder = defaultCommand.builder
    if (typeof builder === 'function') {
      builder(yargs)
    } else {
      Object.keys(builder).forEach((key) => {
        yargs.option(key, builder[key])
      })
    }
  }

  // transcribe all positional arguments "command <foo> <bar> [apple]"
  // onto argv.
  function populatePositionals (commandHandler, argv, context, yargs) {
    argv._ = argv._.slice(context.commands.length) // nuke the current commands
    const demanded = commandHandler.demanded.slice(0)
    const optional = commandHandler.optional.slice(0)
    const positionalMap = {}

    validation.positionalCount(demanded.length, argv._.length)

    while (demanded.length) {
      const demand = demanded.shift()
      populatePositional(demand, argv, positionalMap)
    }

    while (optional.length) {
      const maybe = optional.shift()
      populatePositional(maybe, argv, positionalMap)
    }

    argv._ = context.commands.concat(argv._)

    postProcessPositionals(argv, positionalMap, self.cmdToParseOptions(commandHandler.original))

    return positionalMap
  }

  function populatePositional (positional, argv, positionalMap, parseOptions) {
    const cmd = positional.cmd[0]
    if (positional.variadic) {
      positionalMap[cmd] = argv._.splice(0).map(String)
    } else {
      if (argv._.length) positionalMap[cmd] = [String(argv._.shift())]
    }
  }

  // we run yargs-parser against the positional arguments
  // applying the same parsing logic used for flags.
  function postProcessPositionals (argv, positionalMap, parseOptions) {
    // combine the parsing hints we've inferred from the command
    // string with explicitly configured parsing hints.
    const options = Object.assign({}, yargs.getOptions())
    options.default = Object.assign(parseOptions.default, options.default)
    options.alias = Object.assign(parseOptions.alias, options.alias)
    options.array = options.array.concat(parseOptions.array)
    delete options.config //  don't load config when processing positionals.

    const unparsed = []
    Object.keys(positionalMap).forEach((key) => {
      positionalMap[key].map((value) => {
        unparsed.push(`--${key}`)
        unparsed.push(value)
      })
    })

    // short-circuit parse.
    if (!unparsed.length) return

    const config = Object.assign({}, options.configuration, {
      'populate--': true
    })
    const parsed = Parser.detailed(unparsed, Object.assign({}, options, {
      configuration: config
    }))

    if (parsed.error) {
      yargs.getUsageInstance().fail(parsed.error.message, parsed.error)
    } else {
      // only copy over positional keys (don't overwrite
      // flag arguments that were already parsed).
      const positionalKeys = Object.keys(positionalMap)
      Object.keys(positionalMap).forEach((key) => {
        [].push.apply(positionalKeys, parsed.aliases[key])
      })

      Object.keys(parsed.argv).forEach((key) => {
        if (positionalKeys.indexOf(key) !== -1) {
          // any new aliases need to be placed in positionalMap, which
          // is used for validation.
          if (!positionalMap[key]) positionalMap[key] = parsed.argv[key]
          argv[key] = parsed.argv[key]
        }
      })
    }
  }

  self.cmdToParseOptions = function (cmdString) {
    const parseOptions = {
      array: [],
      default: {},
      alias: {},
      demand: {}
    }

    const parsed = self.parseCommand(cmdString)
    parsed.demanded.forEach((d) => {
      const cmds = d.cmd.slice(0)
      const cmd = cmds.shift()
      if (d.variadic) {
        parseOptions.array.push(cmd)
        parseOptions.default[cmd] = []
      }
      cmds.forEach((c) => {
        parseOptions.alias[cmd] = c
      })
      parseOptions.demand[cmd] = true
    })

    parsed.optional.forEach((o) => {
      const cmds = o.cmd.slice(0)
      const cmd = cmds.shift()
      if (o.variadic) {
        parseOptions.array.push(cmd)
        parseOptions.default[cmd] = []
      }
      cmds.forEach((c) => {
        parseOptions.alias[cmd] = c
      })
    })

    return parseOptions
  }

  self.reset = () => {
    handlers = {}
    aliasMap = {}
    defaultCommand = undefined
    return self
  }

  // used by yargs.parse() to freeze
  // the state of commands such that
  // we can apply .parse() multiple times
  // with the same yargs instance.
  let frozens = []
  self.freeze = () => {
    let frozen = {}
    frozens.push(frozen)
    frozen.handlers = handlers
    frozen.aliasMap = aliasMap
    frozen.defaultCommand = defaultCommand
  }
  self.unfreeze = () => {
    let frozen = frozens.pop()
    handlers = frozen.handlers
    aliasMap = frozen.aliasMap
    defaultCommand = frozen.defaultCommand
  }

  return self
}
