/*
 * grunt-force
 * https://github.com/couchand/grunt-force
 *
 * Copyright (c) 2013 Andrew Couch
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

  grunt.registerMultiTask('force', 'Interact with a Salesforce.com environment', function(sftask) {
    var done = this.async();
    var options = this.options();
    var sfdc = require('../lib/force-0.1.0.js');
    var promise = require('node-promise');
    var file_groups = this.files;

    grunt.log.writeln('force plugin executing task '+sftask);
    grunt.log.writeln('loading credentials from '+options.credentials);

    var credfile = grunt.file.read(options.credentials);
    var module = {};
    eval(credfile);
    var creds = module.exports;

    grunt.log.writeln('logging in to '+creds.login_url+' as '+creds.username);

    if ( sftask !== 'deploy' ) {
      grunt.fail.warn('unknown task');
      return 42;
    }

    var conn;
    var data = {};

    sfdc.connect(creds).then(function(c) {
      grunt.log.writeln('logged in successfully');
      conn = c;

      grunt.log.writeln('looking for container');
      return conn.tooling.query('select Id from MetadataContainer where Name = \'' + options.container + "'");
    }).then(function(containers) {
      if ( containers && containers.length ) {
        grunt.log.writeln('found container');
        // found container, use it
        var now = new promise.Deferred();
        now.resolve( containers[0].Id );
        return now;
      }
      return conn.tooling.insert('MetadataContainer', { 'Name': options.container });
    }).then(function(new_id) {

      data.containerId = new_id;
      var junctionInserts = [];

      grunt.log.writeln('created MetadataContainer with Id '+new_id);
      grunt.log.writeln('creating junction objects now...');

      // Iterate over all specified file groups.
      file_groups.forEach(function(fileObj) {
        // The source files to be concatenated. The "nonull" option is used
        // to retain invalid files/patterns so they can be warned about.
        var files = grunt.file.expand({nonull: true}, fileObj.src);

        files.map(function(filepath) {
          var class_name = filepath.match(/\/([^\/]*)\.cls$/)[1];

          // Warn if a source file/pattern was invalid.
          if (!grunt.file.exists(filepath)) {
            grunt.log.error('Source file "' + filepath + '" not found.');
            return '';
          }

          grunt.log.writeln('adding class ' + class_name);

          junctionInserts.push(
            conn.query('select Id from ApexClass where Name = \''+class_name+"'").then(function(classes) {
              var classId = classes[0].Id;
              grunt.log.writeln('found class '+class_name+' with id '+classId);

              return conn.insert('ApexClassMember', {
                'MetadataContainerId': data.containerId,
                'ContentEntityId': classId,
                'Body': grunt.file.read(filepath)
              });
            })
          );
        });
      });

      grunt.log.writeln('waiting for all adds to complete');

      return promise.all.apply(promise, junctionInserts);
    }).then(function(new_members) {
      grunt.log.writeln('all adds complete');

      new_members.map(function(member) {
        grunt.log.writeln('new member id' + member);
      });

      grunt.log.writeln('submitting deployment request');

      return conn.tooling.deploy(data.containerId);
    }).then(function(results) {

      grunt.log.writeln('deployment complete');
      done();
    });
  });

};

@@ -358,189 +358,388 @@
 var 
-sfdc = require('../lib/force-0.1.0.js'
+file_groups = this.files;%0A%0A    grunt.log.writeln('force plugin executing task '+sftask
 );%0A
+%0A
     
-var promise = require('node-promise');%0A    var file_groups = this.files;%0A%0A    grunt.log.writeln('force plugin executing task '+sftask
+if ( sftask !== 'deploy' ) %7B%0A      grunt.fail.warn('unknown task');%0A      return 42;%0A    %7D%0A%0A    login(options).then(function(conn) %7B%0A      return deploy(conn, file_groups, options);%0A    %7D).then(done);%0A  %7D);%0A%0A  function login(options) %7B%0A    var sfdc = require('../lib/force-0.1.0.js'
 );%0A
+%0A
     
@@ -1026,72 +1026,101 @@
     
-if ( sftask !== 'deploy' ) %7B%0A      grunt.fail.warn('unknown task
+return sfdc.connect(creds).then(function(c) %7B%0A      grunt.log.writeln('logged in successfully
 ');%0A
@@ -1136,100 +1136,76 @@
 urn 
-42
+c
 ;%0A    %7D
-%0A%0A    var conn;%0A    var data = %7B%7D;%0A%0A    sfdc.connect(creds).then(func
+);%0A  %7D%0A%0A  function deploy(conn, file_groups, op
 tion
-(c
+s
 ) %7B%0A    
   gr
@@ -1204,74 +1204,67 @@
     
-  grunt.log.writeln('logged in successfully');%0A      conn = c
+var promise = require('node-promise');%0A    var data = %7B%7D
 ;%0A%0A
-  
     
@@ -1303,26 +1303,25 @@
 ontainer');%0A
-  
+%0A
     return c
@@ -1415,24 +1415,16 @@
 r + %22'%22)
-;%0A    %7D)
 .then(fu
@@ -3731,22 +3731,8 @@
 ');%0A
-      done();%0A
     
@@ -3738,15 +3738,13 @@
  %7D);%0A  %7D
-);
 %0A%0A%7D;%0A

refactor login and deployment and use promises