import 'colors'
import { join } from 'path'
import {
  isInitialized,
  map,
  onlyPackage,
  exec as execCmd,
  separator,
  log
} from '../util'

export const plugin = function exec (program, config, directory) {
  program.command(command).description(description)
    .option('-o, --only <packageName>', 'Only execute in a single package directory')
    .action((...args) => action(config, directory, ...args))
}

const command = 'exec [command...]'
const description = 'Execute a command in all packages'

// exported for testing
export function action (config, workingDir, args, options) {
  isInitialized(config, 'exec')

  const packages = options.parent.only
    ? onlyPackage(options.parent.only, config.packages)
    : config.packages

  if (packages.length === 0) {
    if (options.only) {
      return log('Cannot find package ' + options.parent.only)
    }
    return log('Cannot find any packages to execute your command :(')
  }

  const cmd = args.shift()

  // return promise for testing
  return Promise.all(map(packages, function (packageName) {
    const packageDir = join(workingDir, packageName)
    const name = require(join(packageDir, 'package.json')).name

    return execCmd(cmd, args, {
      cwd: packageDir,
      stdio: 'inherit',
      detached: true,
      env: Object.create(process.env),
      start: separator(name) + '\n' + '$ ' + (cmd + ' ' + args.join(' ')).white + '\n\n',
      stop: separator()
    })
  }))
}

import 'colors'
import { join } from 'path'
import {
  isInitialized,
  map,
  onlyPackage,
  exec as execCmd,
  separator,
  log
} from '../util'

export const plugin = function exec (program, config, directory) {
  program.command(command).description(description)
    .option('-o, --only <packageName>', 'Only execute in a single package directory')
    .action((...args) => action(config, directory, ...args))
}

const command = 'exec [command...]'
const description = 'Execute a command in all packages'

// exported for testing
export function action (config, workingDir, args, options) {
  isInitialized(config, 'exec')

  const packages = options.parent.only
    ? onlyPackage(options.parent.only, config.packages)
    : config.packages

  if (packages.length === 0) {
    if (options.only) {
      return log('Cannot find package ' + options.parent.only)
    }
    return log('Cannot find any packages to execute your command :(')
  }

  const cmd = args.shift()

  const outputs = []

  function runCommand (packageName, next) {
    const packageDir = join(workingDir, packageName)
    const name = require(join(packageDir, 'package.json')).name

    const output = execCmd(cmd, args, {
      cwd: packageDir,
      stdio: 'inherit',
      detached: true,
      env: Object.create(process.env),
      start: separator(name) + '\n' + '$ ' + (cmd + ' ' + args.join(' ')).white + '\n\n',
      stop: separator()
    })

    outputs.push(output)

    output.then(() => {
      next()
    })
  }

  function next () {
    if (packages.length > 0) {
      const packageName = packages.shift()
      runCommand(packageName, next)
    }
  }

  next()

  return Promise.all(outputs)
}

make exec entirely synchronous