text: 'use strict'
  
  const fs = require('fs')
  const path = require('path')
  const findUp = require('find-up')
  const testExclude = require('test-exclude')
  const Yargs = require('yargs/yargs')
  
  var Config = {}
  
  function guessCWD (cwd) {
    cwd = cwd || process.env.NYC_CWD || process.cwd()
    const pkgPath = findUp.sync('package.json', { cwd: cwd })
    if (pkgPath) {
      cwd = path.dirname(pkgPath)
    }
    return cwd
  }
  
  Config.loadConfig = function (argv, cwd) {
    const rcOptions = [
      argv.nycrcPath || '.nycrc',
      '.nycrc.json',
      'nyc.config.js'
    ]
    const rcPath = findUp.sync(rcOptions, { cwd: guessCWD(cwd) })
    let config = {}
  
    if (rcPath) {
      if (rcPath.toLowerCase().endsWith('.js')) {
        config = require(rcPath)
      } else {
        config = JSON.parse(
          fs.readFileSync(rcPath, 'utf-8')
        )
      }
    }
  
    if (config.require) config.require = [].concat(config.require)
    if (config.extension) config.extension = [].concat(config.extension)
    if (config.exclude) config.exclude = [].concat(config.exclude)
    if (config.include) config.include = [].concat(config.include)
  
    return config
  }
  
  // build a yargs object, omitting any settings
  // that would cause the application to exit early.
  Config.buildYargs = function (cwd) {
    cwd = guessCWD(cwd)
    return Yargs([])
      .usage('$0 [command] [options]')
      .usage('$0 [options] [bin-to-instrument]')
      .option('reporter', {
        alias: 'r',
        describe: 'coverage reporter(s) to use',
        default: 'text',
        global: false
      })
      .option('report-dir', {
        describe: 'directory to output coverage reports in',
        default: 'coverage',
        global: false
      })
      .option('silent', {
        alias: 's',
        default: false,
        type: 'boolean',
        describe: "don't output a report after tests finish running",
        global: false
      })
      .option('all', {
        alias: 'a',
        default: false,
        type: 'boolean',
        describe: 'whether or not to instrument all files of the project (not just the ones touched by your test suite)',
        global: false
      })
      .option('exclude', {
        alias: 'x',
        default: testExclude.defaultExclude,
        describe: 'a list of specific files and directories that should be excluded from coverage, glob patterns are supported, node_modules is always excluded',
        global: false
      })
      .option('exclude-after-remap', {
        default: true,
        type: 'boolean',
        description: 'should exclude logic be performed after the source-map remaps filenames?',
        global: false
      })
      .option('exclude-node-modules', {
        default: true,
        type: 'boolean',
        describe: 'whether or not to exclude all node_module folders (i.e. **/node_modules/**) by default',
        global: false
      })
      .option('include', {
        alias: 'n',
        default: [],
        describe: 'a list of specific files that should be covered, glob patterns are supported',
        global: false
      })
      .option('cwd', {
        describe: 'working directory used when resolving paths',
        default: cwd
      })
      .option('require', {
        alias: 'i',
        default: [],
        describe: 'a list of additional modules that nyc should attempt to require in its subprocess, e.g., @babel/register, @babel/polyfill',
        global: false
      })
      .option('eager', {
        default: false,
        type: 'boolean',
        describe: 'instantiate the instrumenter at startup (see https://git.io/vMKZ9)',
        global: false
      })
      .option('cache', {
        alias: 'c',
        default: true,
        type: 'boolean',
        describe: 'cache instrumentation results for improved performance',
        global: false
      })
      .option('cache-dir', {
        describe: 'explicitly set location for instrumentation cache',
        global: false
      })
      .option('babel-cache', {
        default: false,
        type: 'boolean',
        describe: 'cache babel transpilation results for improved performance',
        global: false
      })
      .option('es-modules', {
        default: true,
        type: 'boolean',
        describe: 'tell the instrumenter to treat files as ES Modules',
        global: false
      })
      .option('extension', {
        alias: 'e',
        default: [],
        describe: 'a list of extensions that nyc should handle in addition to .js',
        global: false
      })
      .option('check-coverage', {
        type: 'boolean',
        default: false,
        describe: 'check whether coverage is within thresholds provided',
        global: false
      })
      .option('branches', {
        default: 0,
        description: 'what % of branches must be covered?',
        global: false
      })
      .option('functions', {
        default: 0,
        description: 'what % of functions must be covered?',
        global: false
      })
      .option('lines', {
        default: 90,
        description: 'what % of lines must be covered?',
        global: false
      })
      .option('statements', {
        default: 0,
        description: 'what % of statements must be covered?',
        global: false
      })
      .option('source-map', {
        default: true,
        type: 'boolean',
        description: 'should nyc detect and handle source maps?',
        global: false
      })
      .option('per-file', {
        default: false,
        type: 'boolean',
        description: 'check thresholds per file',
        global: false
      })
      .option('produce-source-map', {
        default: false,
        type: 'boolean',
        description: "should nyc's instrumenter produce source maps?",
        global: false
      })
      .option('compact', {
        default: true,
        type: 'boolean',
        description: 'should the output be compacted?'
      })
      .option('preserve-comments', {
        default: true,
        type: 'boolean',
        description: 'should comments be preserved in the output?'
      })
      .option('instrument', {
        default: true,
        type: 'boolean',
        description: 'should nyc handle instrumentation?',
        global: false
      })
      .option('hook-require', {
        default: true,
        type: 'boolean',
        description: 'should nyc wrap require?',
        global: false
      })
      .option('hook-run-in-context', {
        default: false,
        type: 'boolean',
        description: 'should nyc wrap vm.runInContext?',
        global: false
      })
      .option('hook-run-in-this-context', {
        default: false,
        type: 'boolean',
        description: 'should nyc wrap vm.runInThisContext?',
        global: false
      })
      .option('show-process-tree', {
        describe: 'display the tree of spawned processes',
        default: false,
        type: 'boolean',
        global: false
      })
      .option('clean', {
        describe: 'should the .nyc_output folder be cleaned before executing tests',
        default: true,
        type: 'boolean',
        global: false
      })
      .option('nycrc-path', {
        default: '.nycrc',
        description: 'specify a different .nycrc path',
        global: false
      })
      .option('temp-dir', {
        alias: 't',
        describe: 'directory to output raw coverage information to',
        default: './.nyc_output',
        global: false
      })
      .option('temp-directory', {
        hidden: true,
        global: false
      })
      .option('skip-empty', {
        describe: 'don\'t show empty files (no lines of code) in report',
        default: false,
        type: 'boolean',
        global: false
      })
      .option('skip-full', {
        describe: 'don\'t show files with 100% statement, branch, and function coverage',
        default: false,
        type: 'boolean',
        global: false
      })
      .pkgConf('nyc', cwd)
      .example('$0 npm test', 'instrument your tests with coverage')
      .example('$0 --require @babel/register npm test', 'instrument your tests with coverage and transpile with Babel')
      .example('$0 report --reporter=text-lcov', 'output lcov report after running your tests')
      .epilog('visit https://git.io/vHysA for list of available reporters')
      .boolean('h')
      .boolean('version')
      .help(false)
      .version(false)
  }
  
  // we add operations that would make yargs
  // exit post-hoc, allowing for a multi-pass
  // parsing step.
  Config.addCommandsAndHelp = function (yargs) {
    return yargs
      .help('h')
      .alias('h', 'help')
      .version()
      .command(require('../lib/commands/check-coverage'))
      .command(require('../lib/commands/instrument'))
      .command(require('../lib/commands/report'))
      .command(require('../lib/commands/merge'))
  }
  
  module.exports = Config
  