var fs = require('fs'),
  through = require('through2'),
  rename = require('gulp-rename'),
  browserify = require('gulp-browserify'),
  gutil = require('gulp-util'),
  filter = require('gulp-filter'),
  path = require("path"),
  join = require('gwm-util').asyncJoin,
  util = require('./util'),
  watch = require('gulp-watch'),
  map = require('map-stream'),
  plumber = require('gulp-plumber'),
  callbackHandler = require('gwm-util').callback,
  sectionEntryPoint = require('./section-entry-point');

module.exports = function(options, callback) {
  var plugins = options.plugins;

  return function() {
    gutil.log('gulp-web-modules:section-builder: building section: \'' + options.section + '\'');

    var blocker = join(callback);
    handleJavascriptFiles(blocker.newCallback());
    handleCSSFiles(blocker.newCallback());
    handleAdditional(blocker.newCallback())
    blocker.complete();
  }

  function renameToTempDir() {
    return map(function(file, callback) {
      var tmpPathBase = path.join(file.cwd, options.tmpPath);
      file.base = tmpPathBase;
      file.path = file.base + path.basename(file.path);
      callback(null, file);
    });
  }

  function setGlobal() {
    return through.obj(function(file, enc, cb) {
      file.contents = Buffer.concat([new Buffer('\nvar self=(typeof window!=="undefined")?window:{};var global=self;'), file.contents]);
      this.push(file);
      cb();
    });
  }

  function handleAdditional(callback) {
    // FIXME add additional section builders
  }

  function handleJavascriptFiles(jsCallback, noWatch) {
    var pluginContext = 'javascript',
        callbackExecuted;

    if (options.watch && !noWatch) {
      var watchGlobs = util.pluginGroupGlobs(pluginContext, options);
      watchGlobs.push(options.srcPath + 'js/**/*');
      util.src(watchGlobs, options)
          .pipe(plumber())
          .pipe(watch({}, function() {
            handleJavascriptFiles(!callbackExecuted && callback, true);
            callbackExecuted = true;
          }))
      callback && callback();
      return;
    }

    var pipeline = gulp.src(options.srcPath + 'js/**/*');
    pipeline = pipeline.pipe(sectionEntryPoint(options));
    pipeline = util.pipeIf('beforeMerge', pluginContext, pipeline, options);
    var browserifyTransforms = util.pluginGroup('transform', pluginContext, options).map(function(entry) {
      return entry.plugin;
    });

    // filter all js files so only the entry file is present
    var fileName = options.section + '/js/__entry.js';
    pipeline = pipeline.pipe(filter(function(file) {
      if (file.path.indexOf(fileName) >= 0) {
        return true;
      }
    }));

    var browserifyOptions = {};
    if (options.browserify) {
      for (var name in options.browserify) {
        browserifyOptions[name] = options.browserify[name];
      }
    }
    if (browserifyOptions.transform) {
      browserifyOptions.transform.push.apply(browserifyOptions.transform, browserifyTransforms);
    }
    pipeline = pipeline.pipe(browserify(browserifyOptions));

    pipeline = pipeline.pipe(rename(options.section + '.js'));
    pipeline = util.pipeIf('afterMerge', pluginContext, pipeline, options);
    pipeline = pipeline.pipe(require('./section-content-wrapper')(options));
    pipeline = util.pipeIf('complete', pluginContext, pipeline, options);
    if (options.isBase) {
      pipeline = pipeline.pipe(setGlobal());
    }

    pipeline = pipeline.pipe(gulp.dest('./build/sections'));
    if (!noWatch) {
      pipeline.pipe(callbackHandler(callback));
    }
  }

  function handleCSSFiles(callback, noWatch) {
    var pluginContext = 'css',
        callbackExecuted;

    if (options.watch && !noWatch) {
      var watchGlobs = util.pluginGroupGlobs(pluginContext, options);
      watchGlobs.push(options.srcPath + 'styles/**/*')
      util.src(watchGlobs, options)
          .pipe(plumber())
          .pipe(watch({}, function() {
            handleCSSFiles(!callbackExecuted && callback, true);
            callbackExecuted = true;
          }))
      callback && callback();
      return;
    }

        sectionBuildPlugins = util.pluginGroupGlobs(pluginContext, options);
    sectionBuildPlugins.push(options.srcPath + 'styles/**/*');
    var pipeline = util.src(sectionBuildPlugins, options);

    pipeline = util.pipeIf('beforeMerge', pluginContext, pipeline, options);
    pipeline = pipeline.pipe(require('./css-concat')(options));
    pipeline = util.pipeIf('afterMerge', pluginContext, pipeline, options);
    pipeline = pipeline.pipe(rename(options.section + '.css'))
    pipeline = pipeline.pipe(gulp.dest('./build/sections'));
    pipeline = util.pipeIf('complete', pluginContext, pipeline, options);
    if (!noWatch) {
      pipeline.pipe(callbackHandler(callback));
    }
  }
};

@@ -893,25 +893,26 @@
 plete();%0A  %7D
+;
 %0A
-
 %0A  function 
@@ -1836,33 +1836,36 @@
           .pipe(
-p
+newP
 lumber())%0A      
@@ -3873,17 +3873,20 @@
   .pipe(
-p
+newP
 lumber()
@@ -4786,11 +4786,331 @@
   %7D%0A  %7D%0A
-
 %7D;%0A
+%0Afunction trim(str) %7B return str.replace(/%5E%5Cs+%7C%5Cs+$/g, ''); %7D%0Afunction newPlumber() %7B%0A  return plumber(%7B%0A    errorHandler: function(error) %7B%0A      gutil.log(%0A          gutil.colors.cyan('Plumber') + ' found unhandled error:',%0A          gutil.colors.red(trim(error.toString())));%0A      console.log(%22%5C007%22);%0A    %7D%0A  %7D);%0A%7D%0A

add "beep" if the build fails