var gulp = require('gulp');
 var browserify = require('browserify');
 var literalify = require('literalify');
 var source = require("vinyl-source-stream");
 var underscore = require('underscore');
 var react = require('gulp-react');
 var plumber = require('gulp-plumber');
 var less = require('gulp-less');
 
 // define the libraries that live in the global context here
 // key: the module name to use in require('moduleName')
 // value: the object that lives in global context
 var libMap = {
   'jquery': 'window.$',
   'underscore': 'window._',
   'react': 'window.React',
   'backbone': 'window.Backbone',
   'director': 'window.Router'
 };
 
 // config
 var literalifyConf = literalify.configure(libMap);
 var browserifyConf = {
   basedir: '.'
 };
 
 // add the list of module name you want to browserify and expose here
 // the module files stay under client/
 // for example, you want to browserify and expose module1.js, module2.js,
 // module3.js under client/, set
 // modulesList = ['module1', 'module2', 'module3']
 var reactFiles = ['view1', 'todo', 'view2', 'view3', 'index'];
 var backboneFiles = ['todo', 'todos'];
 var libFiles = ['backbone', 'director', 'jquery', 'react', 'underscore'];
 
 // real files
 var reactJsFiles = underscore.map(reactFiles, function(file){return './client/views/' + file + '.js';});
 var reactJsxFiles = underscore.map(reactFiles, function(file){return './client/views/' + file + '.jsx';});
 var backboneJsFiles = underscore.map(backboneFiles, function(file){return './client/models/' + file + '.js';});
 var libJsFiles = underscore.map(libFiles, function(file){return './client/libs/' + file + '.js';});
 
 // destination for js files
 var jsDestPath = './public/javascript/';
 
 // Browserify and expose all modules in client/ to jsDestPath, used for development
 gulp.task('browserify-expose', function(){
   // create browserify instance
   var b = browserify(browserifyConf);
   b.transform(literalifyConf);
 
   // add and expose react views
   underscore.each(reactFiles, function(file){
     var moduleName = file + ".js";
     var modulePath = './client/views/' + moduleName;
     b.require(modulePath, {expose: 'views/' + file});
     b.add(modulePath);
   });
 
   // add and expose backbone models
   underscore.each(backboneFiles, function(file){
     var moduleName = file + ".js";
     var modulePath = './client/models/' + moduleName;
     b.require(modulePath, {expose: 'models/' + file});
     b.add(modulePath);
  });

  // add and expose libs
  underscore.each(libFiles, function(file){
    var moduleName = file + ".js";
    var modulePath = './client/libs/' + moduleName;
    b.require(modulePath, {expose: 'libs/' + file});
    b.add(modulePath);
  });

  // add main file
  b.add('./client/main.js');

  // bundling
  b.bundle().pipe(source('bundle.js')).pipe(gulp.dest(jsDestPath));
});

// Move non-browserify client files to their right place
gulp.task('move-client-files', function(){
  gulp.src('./client/main.js').
    pipe(gulp.dest(jsDestPath));
});

// transform jsx react files in modulesList
gulp.task('transform-jsx', function(){
  gulp.src(reactJsxFiles)
    .pipe(plumber())
    .pipe(react())
    .pipe(gulp.dest('./client/views/'));
});

// transform less files
gulp.task('transform-less', function(){
  gulp.src('./public/stylesheet/*.less')
    .pipe(plumber())
    .pipe(less())
    .pipe(gulp.dest('./public/stylesheet/'));
});

gulp.task('watch', function(){
  gulp.watch(reactJsxFiles, ['transform-jsx']);
  gulp.watch(reactJsFiles, ['browserify-expose']);
  gulp.watch(backboneJsFiles, ['browserify-expose']);
  gulp.watch('./client/main.js', ['browserify-expose']);
  gulp.watch('./public/stylesheet/*.less', ['transform-less']);
});