import chalk from 'chalk'
import _process from 'child_process'
import inquirer, { Answers, InputQuestion, ListQuestion } from 'inquirer'
import jsonFormat from 'json-format'
import path from 'path'
import { config } from '../package.json'
import { log } from '../ulits/log'
import { regVersion } from '../ulits/ulits'
import Base from './base'


interface CliInterface {
  openTool(): void

  openThis(root: string): void

  upload(root: string | object): void

  login(): void

  preview(root: string | object): void

  auto(root: string | object): void

  close(root: string | object): void

  quit(): void

  config(cmd: string, params: string): void

}

export default class Cli extends Base implements CliInterface {
  protected cliRoot: string
  private version: string = '1.0.0'

  constructor() {
    super()
    this.cliRoot = config.cliRoot
  }

  public openTool(): void {
    this._cli('-o')
  }

  public openThis(root = this.projectRoot): void {
    if (this.checkFileIsExists(path.join(root, 'project.config.json'))) {
      this._cli(`-o ${root}`)
    } else {
      log.error('当前目录不是小程序项目，默认打开开发工具', false)
      this.openTool()
    }
  }

  public upload(root: object | string): void {
    const projectRoot = this.__checkRoot(root)
    if (this.checkFileIsExists(path.join(projectRoot, 'project.config.json'))) {
      // 获取默认的版本号
      this.readFile(projectRoot, 'project.config.json').then(file => {
        let projectInfo: any = JSON.parse(file)
        let {version} = projectInfo
        this.version = version
        inquirer.prompt([
          this._selectType(),
          this._remark(),
          this._version()
        ]).then((answers: any) => {
          let {remark, version} = answers
          this._cli(`-u ${version}@${projectRoot} --upload-desc ${remark}`).then(async () => {
            projectInfo.version = version
            this.version = version
            await this.writeFile(projectRoot, 'project.config.json', jsonFormat(projectInfo))
          })
        }).catch((error) => {
          console.log(error)
        })
      })
    } else {
      log.error('当前目录不是小程序项目，请重新选择目录路径')
    }
  }

  public login(): void {
    this._cli('-l')
  }

  public preview(root: string | object): void {
    this._cli(`-p ${this.__checkRoot(root)}`)
  }

  public auto(root: string | object): void {
    this._cli(`--auto-preview ${this.__checkRoot(root)}`)
  }

  private _selectType(): ListQuestion<Answers> {
    const types: string[] = ['版本升级', '特性更新', '修订补丁']
    return {
      type: 'list',
      name: 'selectType',
      message: `当前版本号【${chalk.blue(this.version)}】请选择要更新的类型`,
      choices: types,
      default: types[0],
      filter(input: string): number {
        return types.findIndex(v => v === input)
      }
    }
  }

  private _remark(): InputQuestion<Answers> {
    return {
      type: 'input',
      name: 'remark',
      message: '请输入项目备注：',
      default: `提交时间：${new Date().toLocaleString()}`
    }
  }

  private _version(): InputQuestion<Answers> {
    return {
      type: 'input',
      name: 'version',
      message: answers => `推荐版本号【${chalk.blue(this.__setVersion(answers.selectType))}】`,
      default: answers => this.__setVersion(answers.selectType),
      validate: (input: any): Promise<boolean | string> => {
        return new Promise(resolve => {
          const state: string | boolean = regVersion.test(input) ?
            true :
            chalk.red('请输入正确的版本号，如：1.0.0')
          resolve(state)
        })
      }
    }
  }

  private __setVersion(index: number): string {
    let v: any = this.version.split('.')
    v[index]++
    return v.join('.')
  }



  public close(root: string | object): void {
    this._cli(`--close ${this.__checkRoot(root)}`)
  }


  public quit(): void {
    this._cli('--quit')
  }

  public config(cmd: string, params: string): void {
    switch (cmd) {
      case 'tool':
        this._modifyConfig(params)
        break
      default:
        log.table([
          ['tool <path>', '设置微信开发工具路径']
        ], true)
        break
    }
  }

  private _modifyConfig(root: string): void {
    if (this.checkFileIsExists(root)) {
      this.readFile(this.root, 'package.json').then(file => {
        let json = JSON.parse(file)
        json.config.cliRoot = root
        this.writeFile(this.root, 'package.json', jsonFormat(json)).then(() => {
          log.success('修改cliRoot成功', false)
        })
      })
    } else {
      log.error('请输入正确的路径', false)
    }
  }

  private _cli(cmd: string[] | string): Promise<any> {
    return new Promise((resolve, reject) => {
      const cli = _process.spawn('bash', {
        shell: process.platform === 'win32'
      })
      cli.stdout.on('data', (res) => {
        console.log(res.toString()) // .replace(/[\r\n]/g, '')
        resolve()
      })
      cli.stdout.on('error', (err) => {
        console.log(err)
        reject(err)
      })
      cli.stdin.write(`${this.cliRoot} ${cmd}`)
      cli.stdin.end()
    })
  }

  private __checkRoot(root: string | object): string {
    return typeof root === 'object' ? this.projectRoot : root
  }

}

export const CliFs = new Cli()
