// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

module.exports = function(grunt) {
  var _ = grunt.util._,
      fs = require('fs');

  grunt.registerMultiTask('template', 'generates an html file from a specified template', function(){
    var data = this.data,
        _ = grunt.util._,
        tmpl = _.template(grunt.file.read(data.src), null, data.variables);

    grunt.file.write(data.dest, tmpl(data.variables));
  });

  grunt.registerMultiTask('get_deps', 'Fetch external dependencies', function(version) {
    grunt.log.writeln("Fetching external dependencies");

    var done = this.async(),
        data = this.data,
        target = data.target || "app/addons/",
        settingsFile = fs.existsSync(data.src) ? data.src : "settings.json.default",
        settings = grunt.file.readJSON(settingsFile),
        _ = grunt.util._;

    // This should probably be a helper, though they seem to have been removed
    var fetch = function(deps, command){
      var child_process = require('child_process');
      var async = require('async');
      async.forEach(deps, function(dep, cb) {
        var path = target + dep.name;
        var location = dep.url || dep.path;
        grunt.log.writeln("Fetching: " + dep.name + " (" + location + ")");

        child_process.exec(command(dep, path), function(error, stdout, stderr) {
          grunt.log.writeln(stderr);
          grunt.log.writeln(stdout);
          cb(error);
        });
      }, function(error) {
        if (error) {
          grunt.log.writeln("ERROR: " + error.message);
          return false;
        } else {
          return true;
        }
      });
    };

    var remoteDeps = _.filter(settings.deps, function(dep) { return !! dep.url; });
    grunt.log.writeln(remoteDeps.length + " remote dependencies");
    var remote = fetch(remoteDeps, function(dep, destination){
      return "git clone " + dep.url + " " + destination;
    });

    var localDeps = _.filter(settings.deps, function(dep) { return !! dep.path; });
    grunt.log.writeln(localDeps.length + " local dependencies");
    var local = fetch(localDeps, function(dep, destination){
      // TODO: Windows
      var command = "cp -r " + dep.path + " " + destination;
      grunt.log.writeln(command);
      return command;
    });

    done(remote && local);

  });

  grunt.registerMultiTask('gen_load_addons', 'Generate the load_addons.js file', function() {
    var data = this.data,
        _ = grunt.util._,
        settingsFile = fs.existsSync(data.src) ? data.src : "settings.json.default",
        settings = grunt.file.readJSON(settingsFile),
        template = "app/load_addons.js.underscore",
        dest = "app/load_addons.js",
        deps = _.map(settings.deps, function(dep) {
          return "addons/" + dep.name + "/base";
        });

    var tmpl = _.template(grunt.file.read(template));
    grunt.file.write(dest, tmpl({deps: deps}));
  });

  grunt.registerMultiTask('gen_initialize', 'Generate the app.js file', function() {
    var _ = grunt.util._,
        settings = this.data,
        template = "app/initialize.js.underscore",
        dest = "app/initialize.js"
        tmpl = _.template(grunt.file.read(template)),
        app = {};
      

    _.defaults(app, settings.app, {
      root: '/',
      host: '../..',
      version: "0.0"
    });

    grunt.file.write(dest, tmpl(app));
  });

  grunt.registerMultiTask('mochaSetup','Generate a config.js and runner.html for tests', function(){
    var data = this.data,
        configInfo,
        _ = grunt.util._,
        configTemplateSrc = data.template,
        testFiles = grunt.file.expand(data.files.src);

    var configTemplate = _.template(grunt.file.read(configTemplateSrc));
    // a bit of a nasty hack to read our current config.js and get the info so we can change it 
    // for our testing setup
    var require = {
      config: function (args) {
        configInfo = args;
        configInfo.paths['chai'] = "../test/mocha/chai";
        configInfo.paths['sinon-chai'] = "../test/mocha/sinon-chai";
        configInfo.paths['testUtils'] = "../test/mocha/testUtils";
        configInfo.baseUrl = '../app';
        delete configInfo.deps;
      }
    };

    eval(grunt.file.read(data.config) +'');

    grunt.file.write('./test/test.config.js', configTemplate({configInfo: configInfo, testFiles: testFiles}));
  });
};
