'use strict'
const path = require('path');
const fs = require('fs');
const _ = require('underscore');
const browserify =  require('browserify');
const watchify  = require('watchify');
const exit = require('./exit');

let logDurration = (stream, message) => {
  stream.on('pipe', () => console.time(message));
  stream.on('finish', () => console.timeEnd(message));
}

module.exports = (targetBundle, config, opts) => {

  let basedir = path.resolve('.');
  let targetOutfile = targetBundle.outfile;

  if(!targetOutfile) {
    exit(`bundle must have an outfile`);
  }

  let targetOutfileInfo = path.parse(targetOutfile);
  let externals = _.map(targetBundle.external, (ext) => _.flatten([ext]));

  let targetBasedir = path.join(basedir,targetOutfileInfo.dir);
  // ------------------------------------------------------------------
  //                     bundle external requires
  // ------------------------------------------------------------------

  let xb = browserify({basedir});
  for(let external of externals) {
    let expose = _.last(external);
    xb.require(_.first(external), {expose});
  }

  let xbundle = xb.bundle();
  xbundle.on('error',exit);

  let externalOutfile = targetBundle.externalOutfile;

  if(!externalOutfile) {
    externalOutfile = path.join(targetBasedir,
                                `${targetOutfileInfo.name}-externals.js`);
  }
  let xStream = fs.createWriteStream(externalOutfile);
  logDurration(xStream, `bundled ${targetBundle.target} externals`);
  xbundle.pipe(xStream);

  // ------------------------------------------------------------------
  //                     bundle target
  // ------------------------------------------------------------------

  let main = targetBundle.main;
  if(!main) {
    exit(`${target} requires a main file to bundle`);
  }

  let mainFileInfo = path.parse(main);
  let bConfig = Object.assign({},config,targetBundle,opts);
  if(bConfig.watch) {
    Object.assign(bConfig,{cache: {}, packageCache: {}});
  }
  basedir = path.join(basedir, mainFileInfo.dir);
  let bOpts = Object.assign({},bConfig,{basedir});
  let b = browserify(mainFileInfo.base ,bOpts);
  b.external(_.map(externals,_.last));

  if(bConfig.watch) {
    b.plugin(watchify, {
      poll: bConfig.poll || false
    })
  }

  for(let t of bConfig.transform) {
    b.transform(t);
  }

  let stream = fs.createWriteStream(path.join(targetBasedir, targetOutfileInfo.base));
  logDurration(stream, `bundled ${targetBundle.target} src`);

  let bundle = b.bundle();
  bundle.on('error', exit);
  bundle.pipe(stream);

}

@@ -2328,24 +2328,48 @@
 rm(t);%0A  %7D%0A%0A
+  function bundle() %7B%0A  
   let stream
@@ -2443,16 +2443,18 @@
 base));%0A
+  
   logDur
@@ -2511,44 +2511,131 @@
 %60);%0A
-%0A
   
-let bundle = b.bundle();%0A  bundle
+  b.bundle()%0A      .on('error', exit)%0A      .pipe(stream);%0A  %7D%0A%0A  if(bConfig.watch) %7B%0A    b.on('update', bundle);%0A  %7D%0A  b
 .on(
@@ -2662,22 +2662,10 @@
 ndle
-.pipe(stream
+(
 );%0A
-%0A
 %7D%0A

fix watch