/*jslint node: true */
'use strict';
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var browserify = require('browserify');
var watchify = require('watchify');
var buffer = require('vinyl-buffer');
var source = require('vinyl-source-stream');
var sequence = require('run-sequence');
var browserSync = require('browser-sync');
var fs = require('fs');

var config = {
  fileSaver: {
    scripts: './src/*.js',
  },
  docs: {
    src: './docs/src',
    index: './docs/index.html',
    styles: './docs/assets/stylesheets/**/*.css',
    dest: './docs/dist'
  },
  browserSync: {
    port: '3000',
    server: './docs'
  },
  // Predefined browserify configs to keep tasks DRY
  browserify: {
    fileSaver: {
      type: 'dragular',
      entryPoint: './src/angular-file-saver.js',
      bundleName: 'angular-file-saver.js',
      dest: './dist',
    },
    docs: {
      type: 'docs',
      entryPoint: './docs/assets/js/custom.js',
      bundleName: 'examples.js',
      dest: './docs/dist'
    }
  },
  // A flag attribute to switch modes.
  isProd: false
};

var browserifyDefaults = config.browserify.fileSaver;

function handleErrors(err) {
  $.util.log(err.toString());
  this.emit('end');
}

function getUpdateType() {
  var env = $.util.env;

  if (env.type) {
    return { type: env.type };
  }

  if (env.version) {
    return { version: env.version };
  }

  return { type: 'patch' };
}

function getPackageJsonVersion() {
    return JSON.parse(fs.readFileSync('./package.json', 'utf8')).version;
}

/*
* See http://blog.avisi.nl/2014/04/25/how-to-keep-a-fast-build-with-browserify-and-reactjs/
*/
function buildScript() {

  var bundler = browserify({
    entries: browserifyDefaults.entryPoint,
    debug: false,
    cache: {},
    packageCache: {},
    fullPaths: false,
    standalone: 'angular-file-saver',
  }, watchify.args);

  // Watch files for changes and only rebuilds what it needs to
  if (!config.isProd) {
    bundler = watchify(bundler);
    bundler.on('update', function() {
      rebundle();
    });
  }

  function rebundle() {
    var stream = bundler.bundle();

    return stream.on('error', handleErrors)
      .pipe(source(browserifyDefaults.bundleName))
      .pipe(buffer())
      .pipe(gulp.dest(browserifyDefaults.dest))
      .pipe($.if(config.isProd, $.uglify({
        compress: { drop_console: true }
      })))
      .pipe($.if(config.isProd, $.rename({
        suffix: '.min'
      })))
      .pipe($.size({
        title: 'Scripts: '
      }))
      .pipe(gulp.dest(browserifyDefaults.dest))
      .pipe($.if(browserSync.active, browserSync.stream()));
  }

  return rebundle();
}

gulp.task('browserify', function() {
  return buildScript();
});

gulp.task('styles:docs', function() {

  return gulp.src([
    config.docs.styles
  ])
  .pipe($.concat('examples.css'))
  .pipe(gulp.dest(config.docs.dest))
  .pipe($.if(browserSync.active, browserSync.stream()));
});

gulp.task('serve', function () {

  browserSync({
    port: config.browserSync.port,
    server: {
      baseDir: config.browserSync.server,
    },
    logConnections: true,
    logFileChanges: true,
    notify: true
  });
});

gulp.task('deploy:docs', function() {
  return gulp.src('./docs/**/*')
    .pipe($.ghPages());
});

gulp.task('build', function() {
  config.isProd = true;
  browserifyDefaults = config.browserify.fileSaver;

  sequence(['browserify']);
});

gulp.task('build:docs', function() {
  config.isProd = true;
  browserifyDefaults = config.browserify.docs;

  sequence(['browserify', 'styles:docs']);
});

gulp.task('dev:docs', function() {
  config.isProd = false;
  browserifyDefaults = config.browserify.docs;

  sequence(['browserify', 'styles:docs'], 'watch:docs');
});

gulp.task('watch:docs', ['serve'], function() {
  gulp.watch(config.docs.styles,  ['styles:docs']);
});


gulp.task('release:bump', function() {

  return gulp.src('./*.json')
    .pipe($.bump(getUpdateType()))
    .pipe(gulp.dest('./'));
});

gulp.task('release:commit', ['release:bump'], function() {

  return gulp.src('.')
    .pipe($.git.add())
    .pipe($.git.commit(':octocat: Bump to ' + getPackageJsonVersion()));
});

gulp.task('release:push', ['release:bump', 'release:commit'], function (cb) {
   return $.git.push('origin', 'master', cb);
});

/*
* Automate npm & bower updates.
* $ gulp release --type major - using gulp-bump versioning
* $ gulp release --version 1.1.1 - using explicit version number
*/
gulp.task('release', ['release:bump', 'release:commit', 'release:push']);

gulp.task('default', ['build']);

@@ -4015,32 +4015,73 @@
 '%5D, function() %7B
+%0A  var version = getPackageJsonVersion();
 %0A%0A  return gulp.
@@ -4158,39 +4158,23 @@
  to ' + 
-getPackageJsonV
+v
 ersion
-()
 ));%0A%7D);%0A
@@ -4303,16 +4303,327 @@
 );%0A%7D);%0A%0A
+gulp.task('release:tag', %5B'release:bump', 'release:commit', 'release:push'%5D, function (cb) %7B%0A  var version = getPackageJsonVersion();%0A%0A  return $.git.tag(version, 'Tag: ' + version, function (err) %7B%0A    if (err) %7B%0A      return cb(err);%0A    %7D%0A    $.git.push('origin', 'master', %7Bargs: '--tags'%7D, cb);%0A  %7D);%0A%7D);%0A%0A
 /*%0A* Aut
@@ -4776,16 +4776,16 @@
 mber%0A*/%0A
-
 gulp.tas
@@ -4846,16 +4846,31 @@
 se:push'
+, 'release:tag'
 %5D);%0A%0Agul

Add release:tag task