'use strict';

let gulp = require('gulp');
let $ = require('gulp-load-plugins')();
let argv = require('yargs').argv;
let path = require('path');
let source = require('vinyl-source-stream');
let buffer = require('vinyl-buffer');
let del = require('del');
let browserify = require('browserify');
let sequence = require('run-sequence');
let bs = require('browser-sync').create();
let nodemon = require('nodemon');
let yaml = require('gulp-yaml-validate');

let prod = !!argv.prod || process.env.NODE_ENV == 'production';

let assetPath = ['assets/**', '!assets/dist/**'];

const ts = require('gulp-typescript');

console.log(argv);

let onError = function onError(err) {
  $.util.beep();
  console.log(err);
  this.emit('end');
};

gulp.task('clobber-assets', () => {
  return del(['dist', 'assets/dist']);
});

// CSS

gulp.task('preprocess-css', () => {
  gulp.src('src/styles/all-stylesheets.styl')
    .pipe($.if(!prod, $.sourcemaps.init()))
    .pipe($.stylus({
      'include css': true,
      paths: ['./node_modules'],

    }))
    .pipe($.autoprefixer())
    .pipe($.if(!prod, $.sourcemaps.write()))
    .pipe(gulp.dest('assets/dist/styles'))
    .pipe(bs.stream());

  gulp.src('src/styles/ternary-cube.styl')
    .pipe($.if(!prod, $.sourcemaps.init()))
    .pipe($.stylus({
      'include css': true,
      paths: ['./node_modules'],

    }))
    .pipe($.autoprefixer())
    .pipe($.if(!prod, $.sourcemaps.write()))
    .pipe(gulp.dest('assets/dist/styles'))
    .pipe(bs.stream());
});

// YAML

gulp.task('validate-yaml', () => {
  gulp.src('./src/resources/*.yml')
    .pipe(yaml({ html: false }));
});

// JS

gulp.task('browserify', () => {
  let gulpBrowserify = function (fileIn, fileOut) {
    return browserify({
      entries: fileIn,
      debug: !prod,
      paths: [path.dirname(fileIn), './dist']
    })
      .transform('babelify', { presets: ['es2015'] })
      .bundle()
      .on('error', onError)
      .pipe(source(fileOut))
      .pipe(buffer());
  };

  return gulpBrowserify('./dist/js/client/main.js', 'main.js')
    .pipe($.if(!prod, $.sourcemaps.init({ loadMaps: true })))
    .pipe($.if(prod, $.uglify()))
    .pipe($.if(!prod, $.sourcemaps.write()))
    .pipe(gulp.dest('assets/dist/scripts'))
    .pipe(bs.stream());
});

gulp.task('compile-typescript', () => {
  const tsProject = ts.createProject('tsconfig.json');
  return tsProject.src()
    .pipe(tsProject())
    .js.pipe(gulp.dest('dist'));
});

gulp.task('copy-source', () => {
  const paths = ['src/**', '!src/**/*.ts'];
  return gulp.src(paths)
    .pipe(gulp.dest('dist'));
});

// Other assets

gulp.task('copy-assets', () => {
  return gulp.src(assetPath)
    .pipe(gulp.dest('assets/dist'))
    .pipe(bs.stream({ once: true }));
});

gulp.task('rev-assets', () => {
  return gulp.src('assets/dist/**')
    .pipe($.revAll.revision({
      includeFilesInManifest: ['.css', '.html', '.icns', '.ico', '.jpg', '.js', '.png', '.svg']
    }))
    .pipe(gulp.dest('assets/dist'))
    .pipe($.revAll.manifestFile())
    .pipe(gulp.dest('assets/dist'));
});

gulp.task('wait', (cb) => {
  setTimeout(cb, 2000);
});

gulp.task('watch-source', ['build'], () => {
  gulp.watch(['src/js/**'], ['compile', 'copy', 'scripts']);
  gulp.watch('src/styles/**', ['styles']);
  gulp.watch(['src/views/**', 'src/resources/**'], bs.reload);
  gulp.watch(assetPath, ['assets']);
});

gulp.task('serve', ['watch-source'], () => {
  let runnode = function (env = {}) {
    nodemon({
      script: 'dist/index.js',
      ext: 'js',
      ignore: ['dist/js/client/**', 'gulpfile.js'],
      env: Object.assign({
        NODE_PATH: './dist',
      }, env),
    });
  };

  if (!argv.nobs) {
    bs.init({
      port: 8000,
      logSnippet: false
    }, (err) => {
      runnode({
        BS_SNIPPET: bs.getOption('snippet')
      });
    });
  } else {
    runnode({
      NODE_PATH: `${process.env.NODE_PATH}:./src`,
    });
  }
});

gulp.task('build', (cb) => {
  let args = ['clobber-assets', 'copy-assets', 'compile-typescript', 'copy-source', 'browserify', 'preprocess-css', 'validate-yaml'];

  if (prod) {
    // HACK: Waiting for a little bit means all of the assets actually get rev'd
    args.push('wait');
    args.push('rev-assets');
  }

  args.push(cb);

  sequence.apply(null, args);
});

@@ -408,17 +408,25 @@
 ');%0Alet 
-y
+validateY
 aml = re
@@ -743,28 +743,19 @@
 task('cl
-obber-assets
+ean
 ', () =%3E
@@ -1578,17 +1578,25 @@
   .pipe(
-y
+validateY
 aml(%7B ht
@@ -3118,28 +3118,381 @@
 p.task('
-watch-source
+build', (cb) =%3E %7B%0A  let args = %5B'clean', 'copy-assets', 'compile-typescript', 'copy-source', 'browserify', 'preprocess-css', 'validate-yaml'%5D;%0A%0A  if (prod) %7B%0A    // HACK: Waiting for a little bit means all of the assets actually get rev'd%0A    args.push('wait');%0A    args.push('rev-assets');%0A  %7D%0A%0A  args.push(cb);%0A%0A  sequence.apply(null, args);%0A%7D);%0A%0Agulp.task('watch
 ', %5B'bui
@@ -3740,23 +3740,16 @@
  %5B'watch
--source
 '%5D, () =
@@ -4249,16 +4249,16 @@
 %7D);%0A
+
   %7D%0A%7D);%0A
 %0Agul
@@ -4257,373 +4257,4 @@
 %7D);%0A
-%0Agulp.task('build', (cb) =%3E %7B%0A  let args = %5B'clobber-assets', 'copy-assets', 'compile-typescript', 'copy-source', 'browserify', 'preprocess-css', 'validate-yaml'%5D;%0A%0A  if (prod) %7B%0A    // HACK: Waiting for a little bit means all of the assets actually get rev'd%0A    args.push('wait');%0A    args.push('rev-assets');%0A  %7D%0A%0A  args.push(cb);%0A%0A  sequence.apply(null, args);%0A%7D);%0A

Make tweaks e.g. standardise names of rules