import fs                      from 'fs'
import minify                  from 'html-minify'
import { tidy as htmltidy }    from 'htmltidy'
import mjmlEngine              from './index'
import { version as VERSION }  from '../package.json'

const engine = mjmlEngine.mjml2html

/*
 * The version number is the NPM
 * version number. It should be the same as the MJML engine
 */
const version = () => VERSION

/*
 * Turns a callback style to a Promise style one
 */
const promisify = fn =>
  (...args) =>
    new Promise((resolve, reject) =>
      fn(...args.concat((err, ...data) =>
        err ? reject(err) : resolve(...data))))

/*
 * Minimal Error Handling
 */
const error   = (e) => {
  console.log(e.stack ? e.stack : e)
  process.exit(42)
}

/*
 * Utility functions
 * write: write to a file
 * pretty: prettify an html file
 * read: read a fileexists: ensure the file exists
 */
const write   = promisify(fs.writeFile)
const read    = promisify(fs.readFile)
const exists  = promisify((file, cb) => fs.access(file, fs.R_OK | fs.W_OK, cb))
const pretty  = (html) =>
  promisify(htmltidy)(html, { indent: true, wrap: 0, bare: true })

/*
 * Turns an MJML input file into a pretty HTML file
 * min: boolean that specify the output format (pretty/minified)
 */
const render = (input, { min, output }) => {
  exists(input)
    .then(()      => read(input))
    .then(mjml    => engine(mjml.toString()))
    .then(html    => min ? minify(html) : pretty(html))
    .then(result  => write(output, result))
    .catch(error)
}

/*
 * Watch changes on a specific input file by calling render on each change
 */
const watch = (input, options) =>
  fs.watch(input, (_, file) => render(input, options))

const capitalize = name => name.charAt(0).toUpperCase() + name.slice(1).toLowerCase().replace(/-/g, '')

/*
* Return the code of an MJML component for a given name
*/
const createComponent = (name, ending) => {
  const lowerName = name.toLowerCase()

return `
import React, { Component } from 'react'
import {
  MJMLColumnElement,
  elements,
  registerElement,
} from 'mjml'

/*
 * Wrap your dependencies here.
 */
const {
  ${lowerName}: Mj${name},
} = elements;

const NAME = '${lowerName}'

@MJMLColumnElement({
  tagName: 'mj-${lowerName}',
  content: ' ',

  /*
   * These are your default css attributes
   */
  attributes: {
    'color': '#424242',
    'font-family': 'Helvetica',
    'margin-top': '10px'
  }
})
class ${name} extends Component {

  /*
   * Build your styling here
   */
  getStyles() {
    const { mjAttribute, color } = this.props

    return _.merge({}, this.constructor.baseStyles, {
      text: {
      /*
       * Get the color attribute
       * Example: <mj-${lowerName} color="blue">content</mj-${lowerName}>
       */
        color: mjAttribute('color')
      }
    })
  }

  render() {

    const css = this.getStyles(),
          content = 'Hello World!'

    return (
      <Mj${name} style={ css }>
        { content }
      </MjText>
    )
  }
}

export default ${name}
`
}

/*
 * Create a new component based on the default template
 */
const initComponent = (name, ending) =>
  write(`./${capitalize(name)}.js`, createComponent(capitalize(name), ending))
    .then(() => console.log(`Component created: ${capitalize(name)}`))

module.exports = {
  initComponent: initComponent,
  render: render,
  watch: watch,
  version: version
}

@@ -1990,16 +1990,40 @@
 'react'%0A
+import _ from 'loadash'%0A
 import %7B
@@ -2143,31 +2143,20 @@
 %7B%0A  
-$%7BlowerName%7D: Mj$%7Bname%7D
+text: MjText
 ,%0A%7D 

create component typo in imports