#!/usr/bin/env node
const commander = require('commander')
const packageJson = require('../package.json')
const fs = require('fs')
const path = require('path')
const chalk = require('chalk')
const postcss = require('postcss')
const tailwind = require('tailwindcss')
const resolveConfig = require('tailwindcss/resolveConfig')
const buildHycss = require('../build.hycss')
const buildStyle = require('../build.style')
const hyextTailwindConfig = require('../getHyextTailwindConfig')

const FILENAME = 'styles'

const buildTaskList = [
  {
    type: 'hycss',
    job: css => buildHycss(css),
    filename: `${FILENAME}.hycss`,
    report: filename => {
      console.log(
        chalk.cyan(`The ${filename} has updated in ${path.relative(process.cwd(), __dirname)}.`)
      )
    },
    tailwind: hyextTailwindConfig
  },
  {
    type: 'json',
    job: css => JSON.stringify(buildStyle(css), null, 2),
    filename: `${FILENAME}.json`,
    report: filename => {
      console.log(
        chalk.cyan(`The ${filename} has updated in ${path.relative(process.cwd(), __dirname)}.`)
      )
    },
    tailwind: hyextTailwindConfig // pass undfined or null will throw an error
  }
]

function updtaeFile(task, css) {
  const {job, filename, report} = task
  const result = job(css)
  fs.writeFileSync(path.join(__dirname, '../', filename), result)
  report(filename)
}

function buildOne(tailwindConfig, runTask) {
  const source = `
  @tailwind components;
  @tailwind utilities;
  `

  return postcss([tailwind(tailwindConfig)])
    .process(source, {from: undefined})
    .then(({css}) => {
      return runTask(css)
    })
    .catch(error => {
      console.error('> Error occurred while generating styles')
      console.error(error.stack)
      process.exit(1)
    })
}

async function build(buildType) {
  let beRunTasks = []

  if (buildType === 'both') {
    beRunTasks = buildTaskList
  } else {
    beRunTasks = buildTaskList.filter(task => task.type === buildType)
  }

  if (beRunTasks.length) {
    const userConfig = getConfigFromUser()
    const beRunTaskWorks = beRunTasks.map(task => {
      const resolvedConfig = userConfig !== null
        ? resolveConfig(task.tailwind, userConfig)
        : task.tailwind
      return buildOne(resolvedConfig, css => updtaeFile(task, css))
    })

    await Promise.all(beRunTaskWorks)

    console.log(chalk.yellow(`The Jobs were finished.`))
  } else {
    console.log(chalk.yellow(`The ${buildType} build type was not found, you should use one of 'hycss'|'json'|'both'.`))
  }
}

function getConfigFromUser() {
  const filePath = path.resolve(process.cwd(), 'tailwind.config.js')
  if (fs.existsSync(filePath)) {
    return require(filePath)
  }
  return null
}

commander
  .version(packageJson.version)
  .option('-b, --build <buildType>', `'hycss'|'json'|'both'`)
  .action(cmd => {
    const buildType = cmd.build
    if (buildType !== void 0) {
      build(buildType)
    } else {
      commander.help()
    }
  })

commander.parse(process.argv)
