#!/usr/bin/env node

// Check node version before requiring/doing anything else
// The user may be on a very old node version

// const { chalk, semver } = require('@vue/cli-shared-utils')
const semver = require('semver');
const chalk = require('chalk');

const pkg = require('../package.json');

const requiredVersion = pkg.engines.node;
const leven = require('leven');

function checkNodeVersion(wanted, id) {
  if (!semver.satisfies(process.version, wanted, { includePrerelease: true })) {
    console.log(
      chalk.red(
        'You are using Node ' +
          process.version +
          ', but this version of ' +
          id +
          ' requires Node ' +
          wanted +
          '.\nPlease upgrade your Node version.'
      )
    );
    process.exit(1);
  }
}

checkNodeVersion(requiredVersion, pkg.name);

const fs = require('fs');
const path = require('path');
const slash = require('slash');
const minimist = require('minimist');

// enter debug mode when creating test repo
// if (
//   slash(process.cwd()).indexOf('/packages/test') > 0 &&
//   (fs.existsSync(path.resolve(process.cwd(), '../@vue')) ||
//     fs.existsSync(path.resolve(process.cwd(), '../../@vue')))
// ) {
//   process.env.VUE_CLI_DEBUG = true;
// }

const program = require('commander');
// const loadCommand = require('../lib/util/loadCommand');

program
  .version(`${pkg.name} ${require('../package').version}`)
  .usage('<command> [options]');

program
  .command('create <app-name>')
  .description('create a new project powered by vue-cli-service')
  // .option(
  //   '-p, --preset <presetName>',
  //   'Skip prompts and use saved or remote preset'
  // )
  // .option('-d, --default', 'Skip prompts and use default preset')
  // .option(
  //   '-i, --inlinePreset <json>',
  //   'Skip prompts and use inline JSON string as preset'
  // )
  // .option(
  //   '-m, --packageManager <command>',
  //   'Use specified npm client when installing dependencies'
  // )
  // .option(
  //   '-r, --registry <url>',
  //   'Use specified npm registry when installing dependencies (only for npm)'
  // )
  // .option(
  //   '-g, --git [message]',
  //   'Force git initialization with initial commit message'
  // )
  // .option('-n, --no-git', 'Skip git initialization')
  // .option('-f, --force', 'Overwrite target directory if it exists')
  // .option('--merge', 'Merge target directory if it exists')
  // .option('-c, --clone', 'Use git clone when fetching remote preset')
  // .option('-x, --proxy <proxyUrl>', 'Use specified proxy when creating project')
  // .option('-b, --bare', 'Scaffold project without beginner instructions')
  // .option('--skipGetStarted', 'Skip displaying "Get started" instructions')
  .action((name, options) => {
    // console.log('name :>> ', name);
    // console.log('options :>> ', options);
    // console.log('process.argv :>> ', process.argv.slice(3));
    // console.log('process.argv2 :>> ', minimist(process.argv.slice(3)));
    if (minimist(process.argv.slice(3))._.length > 1) {
      console.log(
        chalk.yellow(
          "\n Info: You provided more than one argument. The first one will be used as the app's name, the rest are ignored."
        )
      );
    }
    // --git makes commander to default git to true
    // if (process.argv.includes('-g') || process.argv.includes('--git')) {
    //   options.forceGit = true;
    // }
    require('../lib/create')(name, options);
  });

program.on('command:*', ([cmd]) => {
  program.outputHelp();
  console.log(`  ` + chalk.red(`Unknown command ${chalk.yellow(cmd)}.`));
  console.log();
  suggestCommands(cmd);
  process.exitCode = 1;
});

// add some useful info on help
program.on('--help', () => {
  console.log();
  console.log(
    `  Run ${chalk.cyan(
      `vue <command> --help`
    )} for detailed usage of given command.`
  );
  console.log();
});

program.commands.forEach(c => c.on('--help', () => console.log()));

// 增加 commander 的错误提示
const enhanceErrorMessages = require('../lib/util/enhanceErrorMessages');

enhanceErrorMessages('missingArgument', argName => {
  return `Missing required argument ${chalk.yellow(`<${argName}>`)}.`;
});

enhanceErrorMessages('unknownOption', optionName => {
  return `Unknown option ${chalk.yellow(optionName)}.`;
});

enhanceErrorMessages('optionMissingArgument', (option, flag) => {
  return (
    `Missing required argument for option ${chalk.yellow(option.flags)}` +
    (flag ? `, got ${chalk.yellow(flag)}` : ``)
  );
});

// process.argv 默认值，argv[0]是应用，argv[1]是要跑的脚本，后续为用户参数；
// https://github.com/tj/commander.js/blob/HEAD/Readme_zh-CN.md#%E9%9B%B6%E7%A2%8E%E7%9F%A5%E8%AF%86
program.parse(process.argv);

function suggestCommands(unknownCommand) {
  const availableCommands = program.commands.map(cmd => cmd._name);

  let suggestion;

  availableCommands.forEach(cmd => {
    const isBestMatch =
      leven(cmd, unknownCommand) < leven(suggestion || '', unknownCommand);
    if (leven(cmd, unknownCommand) < 3 && isBestMatch) {
      suggestion = cmd;
    }
  });

  if (suggestion) {
    console.log(`  ` + chalk.red(`Did you mean ${chalk.yellow(suggestion)}?`));
  }
}
