const ora = require('ora')
const inquirer = require('inquirer')
const { getRepoList, getTagList } = require('./http')
const chalk = require('chalk')
const spawn = require('cross-spawn');
const { cloneRepo } = require('./clone')

const error = chalk.bold.red;
const info = chalk.bold.cyan

// 添加加载动画
async function wrapLoading(fn, message, ...args) {
    const spinner = ora(message);
    // 开始加载动画
    spinner.start();
    
    try {
        // 执行传入方法
        const result = await fn(...args);
        spinner.succeed();
        return result;
    } catch (error) {
        // 状态为修改为失败
        spinner.fail('Request failed...')
    }
}

class Generator {
    constructor (name, targetDir){
        // 目录名称
        this.name = name;
        // 创建位置
        this.targetDir = targetDir;
    }
    
    async confirmMonorepo() {
        const { isMonorepo } = await inquirer.prompt({
            name: 'isMonorepo',
            type: 'confirm',
            message: '是否生成monorepo项目'
        })
        
        return isMonorepo
    }
    
    // 获取用户选择的模板
    // 1）从远程拉取模板数据
    // 2）用户选择自己新下载的模板名称
    // 3）return 用户选择的名称
    async getRepo(isMonorepo) {
        // 1）从远程拉取模板数据
        const repoList = await wrapLoading(getRepoList, '正在拉取远程模板');
        
        if (!repoList || !repoList.length) return;
        
        // 过滤不需要的模板
        const repos = repoList.filter(item => {
            if (isMonorepo) {
                return item.name.includes('monorepo')
            } else {
                return !item.name.includes('monorepo')
            }
        }).map(item => item.name);
        
        // 2）用户选择自己新下载的模板名称
        const { repo } = await inquirer.prompt({
            name: 'repo',
            type: 'list',
            choices: repos,
            message: '请选择一个模板用来创建项目'
        })
        
        // 3）return 用户选择的名称
        return repo;
    }
    
    async getTag(repo) {
        // 1）基于 repo 结果，远程拉取对应的 tag 列表
        const tags = await wrapLoading(getTagList, '正在拉取标签', repo);
        
        if (!tags || !tags.length) return;
        
        // 过滤我们需要的 tag 名称
        const tagsList = tags.map(item => item.name);
        
        // 2）用户选择自己需要下载的 tag
        const { tag } = await inquirer.prompt({
            name: 'tag',
            type: 'list',
            choices: tagsList,
            message: '请选择模板标签'
        })
        
        // 3）return 用户选择的 tag
        return tag
    }
    
    // 1）获取模板名称
    // 2）获取 tag 名称
    // 3）下载模板到模板目录
    async create(){
        
        const isMonorepo = await this.confirmMonorepo()
        
        // 1）获取模板名称
        const repo = await this.getRepo(isMonorepo)
        if (!repo) {
            console.log(error('暂未拉取到远程模板!'))
            return
        }
        const tag = await this.getTag(repo)
        if (!tag) {
            console.log(error('暂未拉取到模板标签!'))
            return
        }
        await wrapLoading(cloneRepo, '等待下载模板...', repo, tag, this.targetDir)
        console.log(`\r\n  创建项目成功`)
        console.log(`\r\n  cd ${info(this.name)}`)
    }
}

module.exports = Generator;
