/**
 * Jake build script
 */
var jake = require('jake'),
    browserify = require('browserify'),
    wrench = require('wrench'),
    CleanCSS = require('clean-css'),
    fs = require('fs');

require('jake-utils');

// constants
var DIST = './dist';
var VIS = DIST + '/vis.js';
var VIS_CSS = DIST + '/vis.css';
var VIS_TMP = DIST + '/vis.js.tmp';
var VIS_MIN = DIST + '/vis.min.js';
var VIS_MIN_CSS = DIST + '/vis.min.css';

/**
 * default task
 */
desc('Default task: build all libraries');
task('default', ['build', 'minify'], function () {
  console.log('done');
});

/**
 * build the visualization library vis.js
 */
desc('Build the visualization library vis.js');
task('build', {async: true}, function () {
  jake.mkdirP(DIST);
  jake.mkdirP(DIST + '/img');

  // concatenate and stringify the css files
  concat({
    src: [
      './src/timeline/component/css/timeline.css',
      './src/timeline/component/css/panel.css',
      './src/timeline/component/css/labelset.css',
      './src/timeline/component/css/itemset.css',
      './src/timeline/component/css/item.css',
      './src/timeline/component/css/timeaxis.css',
      './src/timeline/component/css/currenttime.css',
      './src/timeline/component/css/customtime.css',

      './src/graph/css/graph-manipulation.css',
      './src/graph/css/graph-navigation.css'
    ],
    dest: VIS_CSS,
    separator: '\n'
  });
  console.log('created ' + VIS_CSS);

  // concatenate the script files
  concat({
    dest: VIS_TMP,
    src: [
      './src/module/imports.js',

      './src/shim.js',
      './src/util.js',
      './src/DataSet.js',
      './src/DataView.js',

      './src/timeline/stack.js',
      './src/timeline/TimeStep.js',
      './src/timeline/Range.js',
      './src/timeline/component/Component.js',
      './src/timeline/component/Panel.js',
      './src/timeline/component/RootPanel.js',
      './src/timeline/component/TimeAxis.js',
      './src/timeline/component/CurrentTime.js',
      './src/timeline/component/CustomTime.js',
      './src/timeline/component/ItemSet.js',
      './src/timeline/component/item/*.js',
      './src/timeline/component/Group.js',
      './src/timeline/Timeline.js',

      './src/graph/dotparser.js',
      './src/graph/shapes.js',
      './src/graph/Node.js',
      './src/graph/Edge.js',
      './src/graph/Popup.js',
      './src/graph/Groups.js',
      './src/graph/Images.js',
      './src/graph/graphMixins/physics/PhysicsMixin.js',
      './src/graph/graphMixins/physics/HierarchialRepulsion.js',
      './src/graph/graphMixins/physics/BarnesHut.js',
      './src/graph/graphMixins/physics/Repulsion.js',
      './src/graph/graphMixins/HierarchicalLayoutMixin.js',
      './src/graph/graphMixins/ManipulationMixin.js',
      './src/graph/graphMixins/SectorsMixin.js',
      './src/graph/graphMixins/ClusterMixin.js',
      './src/graph/graphMixins/SelectionMixin.js',
      './src/graph/graphMixins/NavigationMixin.js',
      './src/graph/graphMixins/MixinLoader.js',
      './src/graph/Graph.js',

      './src/module/exports.js'
    ],

    separator: '\n'
  });

  // copy images
  wrench.copyDirSyncRecursive('./src/graph/img', DIST + '/img/graph', {
    forceDelete: true
  });
  wrench.copyDirSyncRecursive('./src/timeline/img', DIST + '/img/timeline', {
    forceDelete: true
  });

  var timeStart = Date.now();
  // bundle the concatenated script and dependencies into one file
  var b = browserify();
  b.add(VIS_TMP);
  b.bundle({
    standalone: 'vis'
  }, function (err, code) {
    if(err) {
      throw err;
    }
    console.log("browserify",Date.now() - timeStart); timeStart = Date.now();
    // add header and footer
    var lib = read('./src/module/header.js') + code;

    // write bundled file
    write(VIS, lib);
    console.log('created js' + VIS);

    // remove temporary file
    fs.unlinkSync(VIS_TMP);

    // update version number and stuff in the javascript files
    replacePlaceholders(VIS);

    complete();
  });
});

/**
 * minify the visualization library vis.js
 */
desc('Minify the visualization library vis.js');
task('minify', {async: true}, function () {
  // minify javascript
  minify({
    src: VIS,
    dest: VIS_MIN,
    header: read('./src/module/header.js')
  });

  // update version number and stuff in the javascript files
  replacePlaceholders(VIS_MIN);

  console.log('created minified ' + VIS_MIN);

  var minified = new CleanCSS().minify(read(VIS_CSS));
  write(VIS_MIN_CSS, minified);
  console.log('created minified ' + VIS_MIN_CSS);
});

/**
 * test task
 */
desc('Test the library');
task('test', function () {
  // TODO: use a testing suite for testing: nodeunit, mocha, tap, ...
  var filelist = new jake.FileList();
  filelist.include([
    './test/**/*.js'
  ]);

  var files = filelist.toArray();
  files.forEach(function (file) {
    require('./' + file);
  });

  console.log('Executed ' + files.length + ' test files successfully');
});

/**
 * replace version, date, and name placeholders in the provided file
 * @param {String} filename
 */
var replacePlaceholders = function (filename) {
  replace({
    replacements: [
      {pattern: '@@date',    replacement: today()},
      {pattern: '@@version', replacement: version()}
    ],
    src: filename
  });
};