fs = require 'fs-extra'
path = require 'path'
gulp = require 'gulp'
gulpUtil = require 'gulp-util'
gulpIf = require 'gulp-if'
gulpGzip = require 'gulp-gzip'
sourceStream = require 'vinyl-source-stream'
browserify = require 'browserify'
watchify = require 'watchify'
uglify = require 'gulp-uglify'
streamify = require 'gulp-streamify'
coffeeReactify = require 'coffee-reactify'
browserifyCss = require 'browserify-css'
_ = require 'lodash'
jade = require 'gulp-jade'
rename = require 'gulp-rename'
manifest = require 'gulp-manifest'
runSequence = require 'run-sequence'

module.exports = class Carte
  watching: false

  install: (gulp, config)->
    custom = require(config)
    fs.writeFileSync(__dirname + '/../shared/custom.json', JSON.stringify(custom))

    gulp.task 'watching', => @watching = true
    gulp.task 'build', ()-> runSequence ['build:html', 'build:script'], 'build:manifest'
    gulp.task 'watch', ()-> runSequence ['watching', 'build:html', 'build:script'], 'build:manifest'

    gulp.task 'build:html', =>
      _config = require('./config')
      gulp.src(__dirname + '/../client.jade')
        .pipe jade(locals: {config: _config}, pretty: true)
        .pipe rename(_config.html_path)
        .pipe gulp.dest(_config.root_dir)

    gulp.task 'build:manifest', =>
      _config = require('./config')
      gulp.src([_config.root_dir + '/**'])
        .pipe manifest
          hash: true
          preferOnline: true
          network: ['http://*', 'https://*', '*']
          filename: 'app.manifest'
          exclude: 'app.manifest'
        .pipe gulp.dest(_config.root_dir)

    gulp.task 'build:script', =>
      @buildScript config: config

  buildScript: (options)->
    config = require(options.config)
    fs.writeFileSync(__dirname + '/../shared/custom.json', JSON.stringify(config))
    dir = config.root_dir
    file = path.basename config.script_path
    browserify = browserify
      cache: {}
      packageCache: {}
      fullPaths: true
      entries: [__dirname + '/../client.coffee']
      extensions: ['.coffee', '.js', '.cjsx', '.css']
    browserify
      .transform coffeeReactify
      .transform browserifyCss,
        rootDir: 'public'
        processRelativeUrl: (relativeUrl)->
          stripQueryStringAndHashFromPath = (url)-> url.split('?')[0].split('#')[0]
          rootDir = path.resolve(process.cwd(), 'public')
          relativePath = stripQueryStringAndHashFromPath(relativeUrl)
          queryStringAndHash = relativeUrl.substring(relativePath.length)
          prefix = '../node_modules/'
          if (_.startsWith(relativePath, prefix))
            vendorPath = 'vendor/' + relativePath.substring(prefix.length)
            source = path.join(rootDir, relativePath)
            target = path.join(rootDir, vendorPath)
            gulpUtil.log('Copying file from ' + JSON.stringify(source) + ' to ' + JSON.stringify(target))
            fs.copySync(source, target)
            return vendorPath + queryStringAndHash
          relativeUrl
    if @watching
      watchified = watchify(browserify)
      watchified.on 'update', ()=> @bundle(browserify, dir, file)
      watchified.on 'log', gulpUtil.log
    @bundle(browserify, dir, file)
  
  bundle: (browserify, dir, file)->
    browserify
      .bundle()
      .pipe sourceStream file
      .pipe gulpIf(!@watching, streamify(uglify(compress: {drop_console: !@watching})))
      .pipe gulpIf(!@watching, gulpGzip())
      .pipe gulp.dest dir
