#!/usr/bin/env node
'use strict'

const node = process.execPath
const fs = require('fs')
const spawn = require('child_process').spawn
const fg = require('foreground-child')
const opener = require('opener')
const colorSupport = require('color-support')
const nycBin = require.resolve('nyc/bin/nyc.js')
const glob = require('glob')
const isexe = require('isexe')
const osHomedir = require('os-homedir')
const yaml = require('js-yaml')
const path = require('path')
const exists = require('fs-exists-cached').sync
const os = require('os')
const isTTY = process.stdin.isTTY || process.env._TAP_IS_TTY === '1'

const coverageServiceTest = process.env.COVERAGE_SERVICE_TEST === 'true'

// NYC will not wrap a module in node_modules.
// So, we need to tell the child proc when it's been added.
// Of course, this can't reasonably be branch-covered, so ignore it.
/* istanbul ignore next */
if (process.env._TAP_COVERAGE_ === '1')
  global.__coverage__ = global.__coverage__ || {}
else if (process.env._TAP_COVERAGE_ === '0') {
  global.__coverage__ = null
  Object.keys(process.env).filter(k => /NYC/.test(k)).forEach(k =>
    process.env[k] = '')
}

/* istanbul ignore next */
if (coverageServiceTest)
  console.log('COVERAGE_SERVICE_TEST')

// Add new coverage services here.
// it'll check for the environ named and pipe appropriately.
//
// Currently only Coveralls is supported, but the infrastructure
// is left in place in case some noble soul fixes the codecov
// module in the future.  See https://github.com/tapjs/node-tap/issues/270
const coverageServices = [
  {
    env: 'COVERALLS_REPO_TOKEN',
    bin: require.resolve('coveralls/bin/coveralls.js'),
    name: 'Coveralls'
  }
]

const main = _ => {
  const args = process.argv.slice(2)

  if (!args.length && isTTY) {
    console.error(usage())
    process.exit(1)
  }

  // set default args
  const defaults = constructDefaultArgs()

  // parse dotfile
  const rcFile = process.env.TAP_RCFILE || (osHomedir() + '/.taprc')
  const rcOptions = parseRcFile(rcFile)

  // supplement defaults with parsed rc options
  Object.keys(rcOptions).forEach(k =>
    defaults[k] = rcOptions[k])

  defaults.rcFile = rcFile

  // parse args
  const options = parseArgs(args, defaults)

  if (!options)
    return

  process.stdout.on('error', er => {
    /* istanbul ignore else */
    if (er.code === 'EPIPE')
      process.exit()
    else
      throw er
  })

  options.files = globFiles(options.files)

  // this is only testable by escaping from the covered environment
  /* istanbul ignore next */
  if ((options.coverageReport || options.checkCoverage) &&
      options.files.length === 0)
    return runCoverageReport(options)

  if (options.files.length === 0) {
    console.error('Reading TAP data from stdin (use "-" argument to suppress)')
    options.files.push('-')
  }

  if (options.files.length === 1 && options.files[0] === '-') {
    if (options.coverage)
      console.error('Coverage disabled because stdin cannot be instrumented')
    setupTapEnv(options)
    stdinOnly(options)
    return
  }

  // By definition, the next block cannot be covered, because
  // they are only relevant when coverage is turned off.
  /* istanbul ignore next */
  if (options.coverage && !global.__coverage__) {
    return respawnWithCoverage(options)
  }

  setupTapEnv(options)
  runTests(options)
}

const constructDefaultArgs = _ => {
  /* istanbul ignore next */
  const defaultTimeout = global.__coverage__ ? 240 : 30

  const defaultArgs = {
    nodeArgs: [],
    nycArgs: [],
    testArgs: [],
    timeout: +process.env.TAP_TIMEOUT || defaultTimeout,
    color: !!colorSupport.level,
    reporter: null,
    files: [],
    grep: [],
    grepInvert: false,
    bail: false,
    saveFile: null,
    pipeToService: false,
    coverageReport: null,
    browser: true,
    coverage: undefined,
    checkCoverage: false,
    branches: 0,
    functions: 0,
    lines: 0,
    statements: 0,
    jobs: 1,
    outputFile: null
  }

  if (process.env.TAP_COLORS !== undefined)
    defaultArgs.color = !!(+process.env.TAP_COLORS)

  return defaultArgs
}

const parseArgs = (args, options) => {
  const singleFlags = {
    b: 'bail',
    B: 'no-bail',
    i: 'invert',
    I: 'no-invert',
    c: 'color',
    C: 'no-color',
    T: 'no-timeout',
    J: 'jobs-auto',
    O: 'only',
    h: 'help',
    '?': 'help',
    v: 'version'
  }

  const singleOpts = {
    j: 'jobs',
    g: 'grep',
    R: 'reporter',
    t: 'timeout',
    s: 'save',
    o: 'output-file'
  }

  // If we're running under Travis-CI with a Coveralls.io token,
  // then it's a safe bet that we ought to output coverage.
  for (let i = 0; i < coverageServices.length && !options.pipeToService; i++) {
    /* istanbul ignore next */
    if (process.env[coverageServices[i].env])
      options.pipeToService = true
  }

  let defaultCoverage = options.pipeToService
  let dumpConfig = false

  for (let i = 0; i < args.length; i++) {
    const arg = args[i]
    if (arg.charAt(0) !== '-' || arg === '-') {
      options.files.push(arg)
      continue
    }

    // short-flags
    if (arg.charAt(1) !== '-' && arg !== '-gc') {
      const expand = []
      for (let f = 1; f < arg.length; f++) {
        const fc = arg.charAt(f)
        const sf = singleFlags[fc]
        const so = singleOpts[fc]
        if (sf)
          expand.push('--' + sf)
        else if (so) {
          const soslice = arg.slice(f + 1)
          const soval = soslice.charAt(0) === '=' ? soslice : '=' + soslice
          expand.push('--' + so + soval)
          f = arg.length
        } else if (arg !== '-' + fc)
          expand.push('-' + fc)
      }
      if (expand.length) {
        args.splice.apply(args, [i, 1].concat(expand))
        i--
        continue
      }
    }

    const argsplit = arg.split('=')
    const key = argsplit.shift()
    const val = argsplit.length ? argsplit.join('=') : null

    switch (key) {
      case '--help':
        console.log(usage())
        return null

      case '--dump-config':
        dumpConfig = true
        continue

      case '--nyc-help':
        nycHelp()
        return null

      case '--nyc-version':
        nycVersion()
        return null

      case '--version':
        console.log(require('../package.json').version)
        return null

      case '--jobs':
        options.jobs = +(val || args[++i])
        continue

      case '--jobs-auto':
        options.jobs = +os.cpus().length
        continue

      case '--coverage-report':
        options.coverageReport = val || args[++i]
        if (options.coverageReport === 'html')
          options.coverageReport = 'lcov'
        defaultCoverage = true
        continue

      case '--no-browser':
        options.browser = false
        continue

      case '--no-coverage-report':
        options.coverageReport = false
        continue

      case '--no-cov': case '--no-coverage':
        options.coverage = false
        continue

      case '--cov': case '--coverage':
        options.coverage = true
        continue

      case '--save':
        options.saveFile = val || args[++i]
        continue

      case '--reporter':
        options.reporter = val || args[++i]
        continue

      case '--gc': case '-gc': case '--expose-gc':
        options.nodeArgs.push('--expose-gc')
        continue

      case '--strict':
        options.nodeArgs.push('--use_strict')
        continue

      case '--debug':
        options.nodeArgs.push('--debug')
        continue

      case '--debug-brk':
        options.nodeArgs.push('--debug-brk')
        continue

      case '--harmony':
        options.nodeArgs.push('--harmony')
        continue

      case '--node-arg': {
        const v = val || args[++i]
        if (v !== undefined)
          options.nodeArgs.push(v)
        continue
      }

      case '--check-coverage':
        defaultCoverage = true
        options.checkCoverage = true
        continue

      case '--test-arg': {
        const v = val || args[++i]
        if (v !== undefined)
          options.testArgs.push(v)
        continue
      }

      case '--nyc-arg': {
        const v = val || args[++i]
        if (v !== undefined)
          options.nycArgs.push(v)
        continue
      }

      case '--100':
        defaultCoverage = true
        options.checkCoverage = true
        options.branches = 100
        options.functions = 100
        options.lines = 100
        options.statements = 100
        continue

      case '--branches':
      case '--functions':
      case '--lines':
      case '--statements':
        defaultCoverage = true
        options.checkCoverage = true
        options[key.slice(2)] = +(val || args[++i])
        continue

      case '--color':
        options.color = true
        continue

      case '--no-color':
        options.color = false
        continue

      case '--output-file': {
        const v = val || args[++i]
        if (v !== undefined)
          options.outputFile = v
        continue
      }

      case '--no-timeout':
        options.timeout = 0
        continue

      case '--timeout':
        options.timeout = +(val || args[++i])
        continue

      case '--invert':
        options.grepInvert = true
        continue

      case '--no-invert':
        options.grepInvert = false
        continue

      case '--grep': {
        const v = val || args[++i]
        if (v !== undefined)
          options.grep.push(strToRegExp(v))
        continue
      }

      case '--bail':
        options.bail = true
        continue

      case '--no-bail':
        options.bail = false
        continue

      case '--only':
        options.only = true
        continue

      case '--':
        options.files = options.files.concat(args.slice(i + 1))
        i = args.length
        continue

      default:
        throw new Error('Unknown argument: ' + arg)
    }
  }

  if (options.coverage === undefined)
    options.coverage = defaultCoverage

  if (process.env.TAP === '1')
    options.reporter = 'tap'

  // default to tap for non-tty envs
  if (!options.reporter)
    options.reporter = options.color ? 'classic' : 'tap'

  if (dumpConfig)
    return console.log(JSON.stringify(options, null, 2))

  return options
}

// Obviously, this bit isn't going to ever be covered, because
// it only runs when we DON'T have coverage enabled, to enable it.
/* istanbul ignore next */
const respawnWithCoverage = options => {
  // Re-spawn with coverage
  const args = [nycBin].concat(
    '--silent',
    '--cache=true',
    options.nycArgs,
    '--',
    process.execArgv,
    process.argv.slice(1)
  )
  process.env._TAP_COVERAGE_ = '1'
  const child = fg(node, args)
  child.removeAllListeners('close')
  child.on('close', (code, signal) =>
    runCoverageReport(options, code, signal))
}

/* istanbul ignore next */
const pipeToCoverageServices = (options, child) => {
  let piped = false
  for (let i = 0; i < coverageServices.length; i++) {
    if (process.env[coverageServices[i].env]) {
      pipeToCoverageService(coverageServices[i], options, child)
      piped = true
    }
  }

  if (!piped)
    throw new Error('unknown service, internal error')
}

/* istanbul ignore next */
const pipeToCoverageService = (service, options, child) => {
  let bin = service.bin

  if (coverageServiceTest) {
    // test scaffolding.
    // don't actually send stuff to the service
    bin = require.resolve('../test-legacy/fixtures/cat.js')
    console.log('%s:%s', service.name, process.env[service.env])
  }

  const ca = spawn(node, [bin], {
    stdio: [ 'pipe', 1, 2 ]
  })

  child.stdout.pipe(ca.stdin)

  ca.on('close', (code, signal) =>
    signal ? process.kill(process.pid, signal)
    : code ? console.log('Error piping coverage to ' + service.name)
    : console.log('Successfully piped to ' + service.name))
}

/* istanbul ignore next */
const runCoverageReport = (options, code, signal) => {
  if (options.checkCoverage)
    runCoverageCheck(options, code, signal)
  else
    runCoverageReportOnly(options, code, signal)
}

/* istanbul ignore next */
const runCoverageReportOnly = (options, code, signal) => {
  const close = (s, c) => {
    if (signal || s) {
      setTimeout(() => {}, 200)
      process.kill(process.pid, signal || s)
    } else if (code || c)
      process.exit(code || c)
  }

  if (options.coverageReport === false)
    return close(code, signal)

  if (!options.coverageReport) {
    if (options.pipeToService || coverageServiceTest)
      options.coverageReport = 'text-lcov'
    else
      options.coverageReport = 'text'
  }

  const args = [nycBin, 'report', '--reporter', options.coverageReport]

  let child
  // automatically hook into coveralls
  if (options.coverageReport === 'text-lcov' && options.pipeToService) {
    child = spawn(node, args, { stdio: [ 0, 'pipe', 2 ] })
    pipeToCoverageServices(options, child)
  } else {
    // otherwise just run the reporter
    child = fg(node, args)
    if (options.coverageReport === 'lcov' && options.browser)
      child.on('exit', () =>
        opener('coverage/lcov-report/index.html'))
  }

  if (code || signal) {
    child.removeAllListeners('close')
    child.on('close', close)
  }
}

/* istanbul ignore next */
const coverageCheckArgs = options => {
  const args = []
  if (options.branches)
    args.push('--branches', options.branches)
  if (options.functions)
    args.push('--functions', options.functions)
  if (options.lines)
    args.push('--lines', options.lines)
  if (options.statements)
    args.push('--statements', options.statements)

  return args
}

/* istanbul ignore next */
const runCoverageCheck = (options, code, signal) => {
  const args = [nycBin, 'check-coverage'].concat(coverageCheckArgs(options))

  const child = fg(node, args)
  child.removeAllListeners('close')
  child.on('close', (c, s) =>
    runCoverageReportOnly(options, code || c, signal || s))
}

const usage = _ => fs.readFileSync(__dirname + '/usage.txt', 'utf8')
    .split('@@REPORTERS@@')
    .join(getReporters())

const nycHelp = _ => fg(node, [nycBin, '--help'])

const nycVersion = _ => console.log(require('nyc/package.json').version)

const getReporters = _ => {
  const types = require('tap-mocha-reporter').types.reduce((str, t) => {
    const ll = str.split('\n').pop().length + t.length
    if (ll < 40)
      return str + ' ' + t
    else
      return str + '\n' + t
  }, '').trim()
  const ind = '                              '
  return ind + types.split('\n').join('\n' + ind)
}

const setupTapEnv = options => {
  process.env.TAP_TIMEOUT = options.timeout
  if (options.color)
    process.env.TAP_COLORS = '1'
  else
    process.env.TAP_COLORS = '0'

  if (options.bail)
    process.env.TAP_BAIL = '1'

  if (options.grepInvert)
    process.env.TAP_GREP_INVERT = '1'

  if (options.grep.length)
    process.env.TAP_GREP = options.grep.map(p => p.toString())
      .join('\n')

  if (options.only)
    process.env.TAP_ONLY = '1'
}

const globFiles = files => files.reduce((acc, f) =>
  acc.concat(f === '-' ? f : glob.sync(f, { nonull: true })), [])

const makeReporter = options =>
  new (require('tap-mocha-reporter'))(options.reporter)

const stdinOnly = options => {
  // if we didn't specify any files, then just passthrough
  // to the reporter, so we don't get '/dev/stdin' in the suite list.
  // We have to pause() before piping to switch streams2 into old-mode
  process.stdin.pause()
  const reporter = makeReporter(options)
  process.stdin.pipe(reporter)
  if (options.outputFile !== null)
    process.stdin.pipe(fs.createWriteStream(options.outputFile))
  process.stdin.resume()
}

const readSaveFile = options => {
  if (options.saveFile)
    try {
      const s = fs.readFileSync(options.saveFile, 'utf8').trim()
      if (s)
        return s.split('\n')
    } catch (er) {}

  return null
}

const saveFails = (options, tap) => {
  if (!options.saveFile)
    return

  let fails = []
  const successes = []
  tap.on('result', res => {
    // we will continue to re-run todo tests, even though they're
    // not technically "failures".
    if (!res.ok && !res.extra.skip)
      fails.push(res.extra.file)
    else
      successes.push(res.extra.file)
  })

  const save = () => {
    fails = fails.reduce((set, f) => {
      f = f.replace(/\\/g, '/')
      if (set.indexOf(f) === -1)
        set.push(f)
      return set
    }, [])

    if (!fails.length)
      try {
        fs.unlinkSync(options.saveFile)
      } catch (er) {}
    else
      try {
        fs.writeFileSync(options.saveFile, fails.join('\n') + '\n')
      } catch (er) {}
  }

  tap.on('bailout', reason => {
    // add any pending test files to the fails list.
    fails.push.apply(fails, options.files.filter(file =>
      successes.indexOf(file) === -1))
    save()
  })

  tap.on('end', save)
}

const filterFiles = (files, saved, parallelOk) =>
  files.filter(file =>
    path.basename(file) === 'tap-parallel-ok' ?
      ((parallelOk[path.resolve(path.dirname(file))] = true), false)
    : path.basename(file) === 'tap-parallel-not-ok' ?
      parallelOk[path.resolve(path.dirname(file))] = false
    : onSavedList(saved, file)
  )

// check if the file is on the list, or if it's a parent dir of
// any items that are on the list.
const onSavedList = (saved, file) =>
  !saved || !saved.length ? true
  : saved.indexOf(file) !== -1 ? true
  : saved.some(f => f.indexOf(file + '/') === 0)

const isParallelOk = (parallelOk, file) => {
  const dir = path.resolve(path.dirname(file))
  return (dir in parallelOk) ? parallelOk[dir]
    : exists(dir + '/tap-parallel-ok')
    ? parallelOk[dir] = true
    : exists(dir + '/tap-parallel-not-ok')
    ? parallelOk[dir] = false
    : dir.length >= process.cwd().length
    ? isParallelOk(parallelOk, dir)
    : true
}

const runAllFiles = (options, saved, tap) => {
  let doStdin = false
  let parallelOk = Object.create(null)

  options.files = filterFiles(options.files, saved, parallelOk)

  for (let i = 0; i < options.files.length; i++) {
    const opt = {}
    const file = options.files[i]

    // Pick up stdin after all the other files are handled.
    if (file === '-') {
      doStdin = true
      continue
    }

    let st
    try {
      st = fs.statSync(file)
    } catch (er) {
      continue
    }

    if (options.timeout)
      opt.timeout = options.timeout * 1000

    opt.file = file
    if (st.isDirectory()) {
      const dir = filterFiles(fs.readdirSync(file).map(f =>
        file + '/' + f), saved, parallelOk)
      options.files.push.apply(options.files, dir)
    } else {
      if (options.jobs > 1)
        opt.buffered = isParallelOk(parallelOk, file) !== false
      if (file.match(/\.js$/)) {
        const args = options.nodeArgs.concat(file).concat(options.testArgs)
        tap.spawn(node, args, opt, file)
      } else if (isexe.sync(options.files[i]))
        tap.spawn(options.files[i], options.testArgs, opt, file)
    }
  }

  if (doStdin)
    tap.stdin()
}

const runTests = options => {
  const saved = readSaveFile(options)

  // At this point, we know we need to use the tap root,
  // because there are 1 or more files to spawn.
  const tap = require('../lib/tap.js')
  tap.runOnly = false

  // greps are passed to children, but not the runner itself
  tap.grep = []
  tap.jobs = options.jobs
  tap.patchProcess()

  // if not -Rtap, then output what the user wants.
  // otherwise just dump to stdout
  tap.pipe(options.reporter === 'tap' ? process.stdout: makeReporter(options))

  // need to replay the first version line, because the previous
  // line will have flushed it out to stdout or the reporter already.
  if (options.outputFile !== null)
    tap.pipe(fs.createWriteStream(options.outputFile)).write('TAP version 13\n')

  saveFails(options, tap)

  runAllFiles(options, saved, tap)

  tap.end()
}

const parseRcFile = path => {
  try {
    const contents = fs.readFileSync(path, 'utf8')
    return yaml.safeLoad(contents) || {}
  } catch (er) {
    // if no dotfile exists, or invalid yaml, fail gracefully
    return {}
  }
}

const strToRegExp = g => {
  const p = g.match(/^\/(.*)\/([a-z]*)$/)
  g = p ? p[1] : g
  const flags = p ? p[2] : ''
  return new RegExp(g, flags)
}

main()
