text: /*---------------------------------------------------------
   * Copyright (C) upcwangying.com. All rights reserved.
   *--------------------------------------------------------*/
  'use strict'
  
  const Generator = require('yeoman-generator')
  const yosay = require('yosay')
  
  const path = require('path')
  const validators = require('../libs/validators')
  
  module.exports = class extends Generator {
    constructor(args, opts) {
      super(args, opts)
      this.option('number', { type: Number })
      this.option('name', { type: String })
  
      this.extensionConfig = Object.create(null)
      this.extensionConfig.installDependencies = false
    }
  
    initializing() {
      // Welcome
      this.log(yosay('Welcome to the lerna generator!'))
  
      this.extensionConfig.type = 'lerna-quickstart'
    }
  
    prompting() {
      const generator = this
      const prompts = {
        // 1. Ask for project name.
        askForProjectName: () => {
          const name = generator.options['name']
          if (name) {
            generator.extensionConfig.name = name
            return Promise.resolve()
          }
  
          return generator
            .prompt({
              type: 'input',
              name: 'name',
              message: "What's the name of your project?",
              default: generator.extensionConfig.name,
              validate: validators.isPluginId,
            })
            .then(displayNameAnswer => {
              generator.extensionConfig.name = displayNameAnswer.name
            })
        },
  
        // 2. Ask for project description.
        askForProjectDesc: () => {
          return generator
            .prompt({
              type: 'input',
              name: 'description',
              message: "What's the description of your project?",
              default: 'A lerna project generated by lerna generator.',
            })
            .then(nameAnswer => {
              generator.extensionConfig.description = nameAnswer.description
            })
        },
  
        // 3. Ask for project author
        askForProjectAuthor: () => {
          return generator
            .prompt({
              type: 'input',
              name: 'author',
              message: "What's the author of your project?",
            })
            .then(descriptionAnswer => {
              generator.extensionConfig.author = descriptionAnswer.author
            })
        },
  
        // 4. Ask for project independent mode
        askForProjectVersion: () => {
          generator.extensionConfig.independent = true
          return generator
            .prompt({
              type: 'confirm',
              name: 'independent',
              message: 'Enable Independent mode in "lerna.json"?',
              default: true,
            })
            .then(gitAnswer => {
              generator.extensionConfig.independent = gitAnswer.independent
            })
        },
  
        // 5. Ask for package scope
        askForPackageScope: () => {
          return generator
            .prompt({
              type: 'input',
              name: 'scope',
              message: "What's the name of your scoped packages?",
            })
            .then(gitAnswer => {
              generator.extensionConfig.scope = gitAnswer.scope
            })
        },
  
        // 5. Ask for project package manager
        askForPackageManager: () => {
          generator.extensionConfig.pkgManager = 'npm'
          return generator
            .prompt({
              type: 'list',
              name: 'pkgManager',
              message: 'Which package manager to use?',
              choices: [
                {
                  name: 'npm',
                  value: 'npm',
                },
                {
                  name: 'yarn',
                  value: 'yarn',
                },
              ],
            })
            .then(pckgManagerAnswer => {
              generator.extensionConfig.pkgManager = pckgManagerAnswer.pkgManager
            })
        },
  
        // 6. Ask for useWorkspaces
        askForProjectWorkspace: () => {
          generator.extensionConfig.useWorkspaces = false
          if (generator.extensionConfig.pkgManager !== 'yarn') {
            return Promise.resolve()
          }
  
          return generator
            .prompt({
              type: 'confirm',
              name: 'useWorkspaces',
              message: 'Enable useWorkspaces in "lerna.json"?',
              default: false,
            })
            .then(gitAnswer => {
              generator.extensionConfig.useWorkspaces = gitAnswer.useWorkspaces
            })
        },
  
        // 7. Ask for num of packages
        askForPackageNum: () => {
          const number = generator.options['number']
          if (number) {
            generator.extensionConfig.number = number
            return Promise.resolve()
          }
  
          let packagePrompt = () => {
            return generator
              .prompt({
                type: 'input',
                name: 'number',
                message: "What's the number of packages in your project?",
                default: 2,
              })
              .then(gitAnswer => {
                if (!isNaN(gitAnswer.number)) {
                  generator.extensionConfig.number = parseInt(gitAnswer.number)
                } else {
                  generator.log('Please enter the number of packages again!')
                  packagePrompt()
                }
              })
          }
  
          return packagePrompt()
        },
  
        // 8. Ask for project author
        askForProjectLicense: () => {
          return generator
            .prompt({
              type: 'input',
              name: 'license',
              message: "What's the license of your project?",
              default: 'MIT',
            })
            .then(descriptionAnswer => {
              generator.extensionConfig.license = descriptionAnswer.license
            })
        },
  
        // 9. Ask for git
        askForGit: () => {
          return generator
            .prompt({
              type: 'confirm',
              name: 'gitInit',
              message: 'Initialize a git repository?',
              default: true,
            })
            .then(gitAnswer => {
              generator.extensionConfig.gitInit = gitAnswer.gitInit
            })
        },
  
        // 10. Ask for git repo url
        askForGitRepoUrl: () => {
          generator.extensionConfig.gitRepo = 'https://github.com/your-name/your-repo-name'
          if (!generator.extensionConfig.gitInit) {
            return Promise.resolve()
          }
  
          return generator
            .prompt({
              type: 'confirm',
              name: 'gitRepo',
              message: "What's the url of your repository?",
            })
            .then(gitAnswer => {
              generator.extensionConfig.gitRepo = gitAnswer.gitRepo
            })
        },
      }
  
      // run all prompts in sequence. Results can be ignored.
      let result = Promise.resolve()
      for (let taskName in prompts) {
        let prompt = prompts[taskName]
        result = result.then(_ => {
          return new Promise((s, r) => {
            setTimeout(_ => prompt().then(s, r), 0) // set timeout is required, otherwise node hangs
          })
        })
      }
      return result
    }
    // Write files
    writing() {
      this.sourceRoot(path.join(__dirname, './templates/' + this.extensionConfig.type))
  
      switch (this.extensionConfig.type) {
        case 'lerna-quickstart':
          this._writingLernaQuickStart()
          break
        default:
          //unknown project type
          break
      }
    }
  
    // Write lerna project
    _writingLernaQuickStart() {
      const context = this.extensionConfig
  
      this.fs.copy(this.sourceRoot() + '/docs', context.name + '/docs')
      this.fs.copy(this.sourceRoot() + '/samples', context.name + '/samples')
  
      if (context.number >= 1) {
        for (let i = 0; i < context.number; i++) {
          this.extensionConfig.pkgDirectory = `pkg${i + 1}`
          if (context.scope) {
            const scope = context.scope.startsWith('@') ? context.scope : `@${context.scope}`
            this.extensionConfig.pkgName = `${scope}/pkg${i + 1}`
          } else {
            this.extensionConfig.pkgName = `pkg${i + 1}`
          }
          this.fs.copyTpl(
            this.sourceRoot() + '/packages/t-pkg/package.json',
            context.name + `/packages/${this.extensionConfig.pkgDirectory}/package.json`,
            context,
          )
        }
      }
  
      if (this.extensionConfig.gitInit) {
        this.fs.copy(this.sourceRoot() + '/.gitignore', context.name + '/.gitignore')
      }
  
      this.fs.copy(this.sourceRoot() + '/.all-contributorsrc', context.name + '/.all-contributorsrc')
      this.fs.copyTpl(this.sourceRoot() + '/.editorconfig', context.name + '/.editorconfig', context)
      this.fs.copyTpl(this.sourceRoot() + '/.eslintignore', context.name + '/.eslintignore', context)
      this.fs.copyTpl(this.sourceRoot() + '/.eslintrc', context.name + '/.eslintrc', context)
      this.fs.copyTpl(
        this.sourceRoot() + '/.prettierignore',
        context.name + '/.prettierignore',
        context,
      )
      this.fs.copyTpl(this.sourceRoot() + '/.prettierrc', context.name + '/.prettierrc', context)
      this.fs.copyTpl(this.sourceRoot() + '/.yarnrc', context.name + '/.yarnrc', context)
      this.fs.copyTpl(this.sourceRoot() + '/CHANGELOG.md', context.name + '/CHANGELOG.md', context)
      this.fs.copyTpl(
        this.sourceRoot() + '/CONTRIBUTING.md',
        context.name + '/CONTRIBUTING.md',
        context,
      )
      this.fs.copyTpl(
        this.sourceRoot() + '/CONTRIBUTORS.md',
        context.name + '/CONTRIBUTORS.md',
        context,
      )
      this.fs.copyTpl(
        this.sourceRoot() + '/jest.config.js',
        context.name + '/jest.config.js',
        context,
      )
      this.fs.copyTpl(this.sourceRoot() + '/jest.setup.js', context.name + '/jest.setup.js', context)
      this.fs.copyTpl(this.sourceRoot() + '/lerna.json', context.name + '/lerna.json', context)
      this.fs.copyTpl(this.sourceRoot() + '/LICENSE.md', context.name + '/LICENSE.md', context)
      this.fs.copyTpl(this.sourceRoot() + '/package.json', context.name + '/package.json', context)
      this.fs.copyTpl(this.sourceRoot() + '/README.md', context.name + '/README.md', context)
  
      this.extensionConfig.installDependencies = true
    }
  
    // Installation
    install() {
      process.chdir(this.extensionConfig.name)
  
      if (this.extensionConfig.installDependencies) {
        this.installDependencies({
          yarn: this.extensionConfig.pkgManager === 'yarn',
          npm: this.extensionConfig.pkgManager === 'npm',
          bower: false,
        })
      }
    }
  
    // End
    end() {
      // Git init
      if (this.extensionConfig.gitInit) {
        this.spawnCommand('git', ['init', '--quiet'])
      }
  
      this.log('')
      this.log('Your project ' + this.extensionConfig.name + ' has been created!')
      this.log('')
    }
  }
  