/**
 * Dependencies
 */

var _ = require("lodash");
var path = require("path");

var gulp = require("gulp");
var gutil = require("gulp-util");
var clean = require("gulp-clean");
var stylus = require("gulp-stylus");
var prefix = require("gulp-autoprefixer");
var connect = require("gulp-connect");
var gutil = require("gulp-util");
var jshint = require("gulp-jshint");
var stylish = require("jshint-stylish");
var mochaPhantomJS = require("gulp-mocha-phantomjs");

var webpack = require("webpack");


/**
 * App Configuration
 */

var config = {
  src: "app",
  dest: "dist",
  srcFullPath: path.join(__dirname, "app"),
  destFullPath: path.join(__dirname, "dist"),
  root: __dirname,

  js: "js",
  assets: "assets",
  styles: "styles",

  port: 3000,
  testPort: 3001
};

config.webpack = {
  context: config.srcFullPath,
  cache: true,
  entry: {
    main: "./js/main.js"
  },
  output: {
    path: path.join(config.destFullPath, config.js),
    publicPath: path.join(config.dest, config.js),
    filename: "[name].bundle.js",
    chunkFilename: "[id].bundle.js",
    sourceMapFilename: "[file].map"
  },
  module: {
    loaders: [
      { test: /\.css$/, loader: "style-loader!css-loader" },
    ]
  },
  resolve: {
    alias: {
      "underscore": "lodash"
    }
  },
  plugins: [
    new webpack.ProvidePlugin({
      jQuery: "jquery",
      $: "jquery",
      _: "lodash"
    })
  ]
};


/**
 * Primary Task
 */

gulp.task("default", ["watch"], function () {});


/**
 * Composite Tasks
 */

gulp.task("build", ["lint", "test-phantom", "clean", "copy", "build:css", "build:js"]);

gulp.task("build-dev", ["clean", "copy", "build:css", "build:js-dev"]);

gulp.task("watch", ["build-dev"], function () {
  gulp.watch(path.join(config.srcFullPath, "**/*"), function () {
    gulp.run("build-dev");
  });
});

gulp.task("watch-reload", ["build-dev", "server"], function () {
  gulp.watch(path.join(config.srcFullPath, "**/*"), function () {
    gulp.run("build-dev");
  });
});

gulp.task("test", ["build:test", "server:test"], function () {
  gulp.watch(path.join(config.srcFullPath, "**/*"), function () {
    gulp.run("build-dev");
  });
});

gulp.task("test-phantom", ["build:test"], function () {
  return gulp
    .src("dist/spec/test-runner.html")
    .pipe(mochaPhantomJS());
});


/**
 * Component Tasks
 */

gulp.task("clean", function () {
  return gulp.src(path.join(config.dest, "*"))
    .pipe(clean());
});

gulp.task("copy", function () {
  return gulp.src(
    path.join(config.srcFullPath, config.assets, "**/*"),
    { base: path.join(config.srcFullPath, config.assets) }
    )
    .pipe(gulp.dest(config.destFullPath));
});

gulp.task("lint", function () {
  return gulp.src([
    path.join(config.srcFullPath, "js", "**/*.js"),
    path.join(config.srcFullPath, "spec/tests/**/*.js"),
    path.join(config.root, "*.js"),
  ])
    .pipe(jshint(path.join(config.root, ".jshintrc")))
    .pipe(jshint.reporter(stylish))
    .pipe(jshint.reporter("fail"));
});

gulp.task("server", connect.server({
  root: [config.destFullPath],
  livereload: true,
  port: config.port
}));

gulp.task("server:test", connect.server({
  root: [config.destFullPath],
  open: {
    file: "spec/test-runner.html"
  },
  livereload: true,
  port: config.testPort
}));


/**
 * CSS
 */

gulp.task("build:css", function () {
  return gulp.src(path.join(config.srcFullPath, config.styles, "*"))
    .pipe(stylus({
      use: ["axis-css"],
      set: ["compress"],
      define: { "ie8": true }
    }))
    .pipe(prefix("last 1 version", "> 1%", "ie 8"))
    .pipe(gulp.dest(path.join(config.destFullPath, "styles")));
});


/**
 * JS
 */

gulp.task("build:js", function (callback) {
  var webpackConf = _.extend({}, config.webpack);

  webpackConf.plugins = webpackConf.plugins.concat([
    new webpack.DefinePlugin({
      "process.env": {
        "NODE_ENV": JSON.stringify("production")
      }
    }),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin()
  ]);

  webpack(webpackConf, function (err, stats) {
    if (err) {
      throw new gutil.PluginError("build:js", err);
    }
    gutil.log("[build:js]", stats.toString({
      colors: true
    }));
    callback();
  });
});

gulp.task("build:js-dev", function (callback) {

  var webpackConf = _.extend({}, config.webpack, {
    devtool: "sourcemap",
    debug: true
  });

  webpack(webpackConf, function (err, stats) {
    if (err) {
      throw new gutil.PluginError("build:js-dev", err);
    }
    gutil.log("[build:js-dev]", stats.toString({
      colors: true
    }));
    callback();
  });
});

/**
 * Tests
 */

gulp.task("build:test", function (callback) {
  gulp.src(path.join(config.srcFullPath, "spec/test-runner.html"))
    .pipe(gulp.dest(path.join(config.destFullPath, "spec")));

  var webpackConf = _.extend({}, config.webpack, {
    entry: {
      test: "./spec/test-runner.js"
    },
    output: {
      path: path.join(config.destFullPath, "spec"),
      publicPath: path.join(config.dest, "spec"),
      filename: "[name].bundle.js"
    },
    devtool: "sourcemap",
    debug: true
  });

  webpack(webpackConf, function (err) {
    if (err) {
      throw new gutil.PluginError("build:js-dev", err);
    }
    callback();
  });
});

@@ -1537,40 +1537,102 @@
 tom%22
+%5D
 , 
-%22clean%22, %22copy%22, %22build:css%22, 
+function () %7B%0A  gulp.run(%22clean%22);%0A  gulp.run(%22copy%22);%0A  gulp.run(%22build:css%22);%0A  gulp.run(
 %22bui
@@ -1637,17 +1637,20 @@
 uild:js%22
-%5D
+);%0A%7D
 );%0A%0Agulp

build process that fails on test-phantom or lint failure