import { testList, testCreate, testGet, testUpdate, testDelete } from './test-allows';
import { forbidList, forbidCreate, forbidGet, forbidUpdate, forbidDelete } from './test-forbids';

function testCrud(test, name, config) {

  function processOption(operationName, configEntry, allowTest, rejectTest, configKeys) {
    if (typeof configEntry !== 'undefined') {
      if (Array.isArray(configEntry)) {
        for (var n = 0, m = configEntry.length; n < m; n++) {
          processOption.call(this, operationName, configEntry[n], allowTest, rejectTest, configKeys);
        }
        return;
      }

      var paramArray = [];
      if (configKeys) {
        for (var i = 0, l = configKeys.length; i < l; i++) {
          paramArray.push(configEntry[configKeys[i]]);
        }
      }
      if (configEntry.message) {
        paramArray.push(configEntry.message);
      }
      paramArray.unshift(name);

      if (configEntry !== false && configEntry.forbid !== true && configEntry.allow !== false) {
        test(operationName.capitalize() + " tests", function() {
          this._grateConfig = config; // todo - make this less sucky (1 of 2, see store-ops)
          Ember.run(this, function() {
            allowTest.apply(this, paramArray)
              .then(invokeAfter);
          });
        });
      } else {
        if (configEntry.statusCode) {
          paramArray.push(configEntry.statusCode);
        }
        test(operationName.capitalize() + " forbidden", function() {
          Ember.run(this, function() {
            rejectTest.apply(this, paramArray)
              .then(invokeAfter);
          });
        });
      }
    }

    function invokeAfter(result) {
      if (typeof configEntry.then === 'function') {
        configEntry.then.call(this, result);
      }
    }
  }

  processOption.call(this, 'list',   config.list,   testList,   forbidList);
  processOption.call(this, 'create', config.create, testCreate, forbidCreate, ['data']);
  processOption.call(this, 'read',   config.read,   testGet,    forbidGet,    ['source']);
  processOption.call(this, 'update', config.update, testUpdate, forbidUpdate, ['source', 'data']);
  processOption.call(this, 'delete', config.delete, testDelete, forbidDelete, ['source']);

}

export { testCrud };

@@ -1675,20 +1675,541 @@
 r(result
+sArray
 ) %7B%0A
+      var promises = %5B%5D,%0A          promise,%0A          payload,%0A          result;%0A%0A      if (!Array.isArray(resultsArray)) %7B%0A        result = resultsArray;%0A        if (result.jqXHR) %7B%0A          payload = result.jqXHR.responseText;%0A%0A          if (payload) try %7B%0A            payload = JSON.parse(payload)%0A          %7D catch (e) %7B%0A            payload = result.jqXHR.responseText;%0A          %7D%0A        %7D%0A      %7D else %7B%0A        result = resultsArray.get('firstObject');%0A        payload = resultsArray.objectAt(1);%0A      %7D%0A%0A
       if
@@ -2259,16 +2259,26 @@
 %0A       
+ promise =
  configE
@@ -2309,25 +2309,310 @@
 ult);%0A      
-%7D
+  if (promise && promise.then) promises.push(promise);%0A      %7D%0A%0A      if (typeof configEntry.payload === 'function') %7B%0A        promise = configEntry.payload.call(this, payload);%0A        if (promise && promise.then) promises.push(promise);%0A      %7D%0A%0A      return Ember.RSVP.all(promises);
 %0A    %7D%0A  %7D%0A%0A

Add feature -> `payload: function(data) { }` payload assertions