(function() {
  var EE, PrettyError, Promise, _, appData, babelify, browserify, builtFiles, cjsxify, fs, log, path, pe, pluginAddModuleExports, presetLatest, presetReact, stringStream, through, toHashName, watchify;

  _ = require("lodash");

  fs = require("fs-extra");

  EE = require("events");

  path = require("path");

  through = require("through");

  Promise = require("bluebird");

  babelify = require("babelify");

  watchify = require("watchify");

  browserify = require("browserify");

  presetReact = require("babel-preset-react");

  presetLatest = require("babel-preset-latest");

  stringStream = require("string-to-stream");

  pluginAddModuleExports = require("babel-plugin-add-module-exports");

  cjsxify = require("./cjsxify");

  appData = require("./app_data");

  toHashName = require('./saved_state').toHashName;

  log = require('debug')('cypress:server:bundle');

  PrettyError = require('pretty-error');

  pe = new PrettyError();

  pe.skipNodeFiles();

  fs = Promise.promisifyAll(fs);

  builtFiles = {};

  module.exports = {
    reset: function() {
      return builtFiles = {};
    },
    outputPath: function(projectRoot, filePath) {
      if (projectRoot == null) {
        projectRoot = "";
      }
      return appData.projectsPath(toHashName(projectRoot), "bundles", filePath);
    },
    build: function(filePath, config) {
      var absolutePath, built, bundle, bundler, emitter, latestBundle, outputPath, ref;
      if (config.isTextTerminal && (built = builtFiles[filePath])) {
        return built;
      }
      log("bundler for project " + config.projectRoot + " for file " + filePath);
      emitter = new EE();
      absolutePath = path.join(config.projectRoot, filePath);
      log("input absolute path " + absolutePath);
      outputPath = this.outputPath(config.projectRoot, filePath);
      log("output path " + absolutePath);
      bundler = browserify({
        entries: [absolutePath],
        extensions: [".js", ".jsx", ".coffee", ".cjsx"],
        cache: {},
        packageCache: {}
      });
      if (!config.isTextTerminal) {
        this._watching = true;
        bundler.plugin(watchify, {
          ignoreWatch: ["**/.git/**", "**/.nyc_output/**", "**/.sass-cache/**", "**/bower_components/**", "**/coverage/**", "**/node_modules/**"]
        });
      }
      bundle = (function(_this) {
        return function() {
          return new Promise(function(resolve, reject) {
            var onError, ws;
            log("making bundle " + outputPath);
            onError = function(err) {
              var ws;
              if (config.isTextTerminal) {
                err.filePath = absolutePath;
                err.originalStack = err.stack;
                return reject(err);
              } else {
                ws = fs.createWriteStream(outputPath);
                ws.on("finish", function() {
                  log("browserify: send error to client: " + err.stack);
                  return resolve();
                });
                ws.on("error", function() {
                  log("browserify: failed to send error to client: " + err.stack);
                  return resolve();
                });
                return stringStream(_this.clientSideError(err)).pipe(ws);
              }
            };
            ws = fs.createWriteStream(outputPath);
            ws.on("finish", function() {
              log("browserify: finished bundling " + outputPath);
              return resolve();
            });
            ws.on("error", onError);
            return bundler.bundle().on("error", onError).pipe(ws);
          });
        };
      })(this);
      bundler.transform(cjsxify).transform(babelify, {
        ast: false,
        babelrc: false,
        plugins: [pluginAddModuleExports],
        presets: [presetLatest, presetReact]
      }).external(["react/addons", "react/lib/ReactContext", "react/lib/ExecutionEnvironment"]);
      bundler.on("update", function(filePaths) {
        var latestBundle;
        return latestBundle = bundle().then(function() {
          var i, len, updatedFilePath;
          for (i = 0, len = filePaths.length; i < len; i++) {
            updatedFilePath = filePaths[i];
            emitter.emit("update", updatedFilePath);
          }
        });
      });
      latestBundle = fs.ensureDirAsync(path.dirname(outputPath)).then(bundle);
      return builtFiles[filePath] = {
        close: (ref = bundler.close) != null ? ref : function() {},
        getLatestBundle: function() {
          return latestBundle;
        },
        addChangeListener: function(onChange) {
          return emitter.on("update", onChange);
        }
      };
    },
    errorMessage: function(err) {
      var ref, ref1, ref2;
      if (err == null) {
        err = {};
      }
      return ((ref = (ref1 = (ref2 = err.stack) != null ? ref2 : err.annotated) != null ? ref1 : err.message) != null ? ref : err.toString()).replace(/\n\s*at.*/g, "").split("From previous event:\n").join("").split("From previous event:").join("");
    },
    clientSideError: function(err) {
      console.error(pe.render(err));
      err = this.errorMessage(err).replace(/\n/g, '{newline}').replace(/\[\d{1,3}m/g, '');
      return "(function () {\n  Cypress.action(\"spec:script:error\", {\n    type: \"BUNDLE_ERROR\",\n    error: " + (JSON.stringify(err)) + "\n  })\n}())";
    }
  };

}).call(this);
