var _ = require('lodash');
var getRandomFloat = require('../lib/get-random-float');
var getRandomInt = require('../lib/get-random-int');

const COMMAND = 'command';
const QUERY = 'query';

function gt (a, b) {
  return a > b;
}

function lt (a, b) {
  return a < b;
}

function randomAttribute (object) {
  return _.sample(Object.keys(object));
}

function compare (operators, a, b) {
  var operator = _.sample(operators);

  return (entity, api) => { return operator(a(entity, api), b(entity, api)); };
}

// TODO - genericize
function getRandomCommand (schema) {
  var command = _.sample(['setVelocity', 'stop', 'applyForce']);

  if (command === 'setVelocity') {
    var velocity = {
      x: getRandomInt(-10, 10),
      y: getRandomInt(-10, 10)
    };

    return (entity, api) => {
      api.setVelocity(entity, velocity);
    };
  }

  if (command === 'stop') {
    return (entity, api) => api.stop(entity);
  };

  if (command === 'applyForce') {
    const forceRange = 0.5;
    const force = {
      x: getRandomFloat(-forceRange, forceRange),
      y: getRandomFloat(-forceRange, forceRange)
    };

    return (entity, api) => api.applyForce(entity, force);
  };
}

function newNode (schema) {
  var actionSelector = getRandomInt(0, 100);

  var randomX = getRandomInt(0, 600);
  var randomY = getRandomInt(0, 400);

  var command = getRandomCommand(schema);
  var alternateCommand = getRandomCommand(schema);


  // There is a 20% chance to emit a node that operates as a NOP if a button is not down
  if (schema.checkButtonDown && actionSelector > 80) {
    var buttonToCheck = _.sample(schema.checkButtonDown.takes);
    var buttonQuery = _.sample(['checkButtonDown']);

    return (entity, api, currentFrame) => {
      if (api[buttonQuery](entity, buttonToCheck, currentFrame)) {
        command(entity, api);
      }
    };
  }

  // There is a 30% chance to emit a node that picks between two nodes depending on an XY position
  // The paucity of this - in a history sense - is probably why circles are so awful
  if (actionSelector > 50) {
    var attributeToCompare = randomAttribute(schema.getPosition.returns);
    var condition = compare(
      [gt, lt],
      function (entity, api) { return api.getPosition(entity)[attributeToCompare]; },
      function (entity, api) { return _.sample([randomX, randomY]); }
    );

    return (entity, api) => {
      if (condition(entity, api)) {
        command(entity, api);
      } else {
        alternateCommand(entity, api);
      }
    };
  };

  if (actionSelector > 25) {
    return (entity, api, currentFrame) => {
      // TODO - do something with collision results aside from checking length
      if (api.checkCollision && api.checkCollision(entity, currentFrame).length > 0) {
        command(entity, api);
      };
    }
  }

  return (entity, api) => {
    command(entity, api);
  };
}

function generateIndividual (schema) {
  var entropy = getRandomInt(1, 20);

  return _.chain(entropy).range().map(() => {
    return newNode(schema);
  }).value();
}

var Seeder = {
  make (schema, numberOfIndividuals) {
    return _.chain(numberOfIndividuals).range().map(() => {
      return generateIndividual(schema);
    }).value();
  }
};

module.exports = Seeder;

@@ -500,16 +500,672 @@
 ; %7D;%0A%7D%0A%0A
+function positionConditional (schema) %7B%0A  const randomX = getRandomInt(0, 600);%0A  const randomY = getRandomInt(0, 400);%0A  const positionToCheck = _.sample(%5BrandomX, randomY%5D);%0A  const attributeToCompare = randomAttribute(schema.getPosition.returns);%0A%0A  return compare(%0A    %5Bgt, lt%5D,%0A    (entity, api) =%3E api.getPosition(entity)%5BattributeToCompare%5D,%0A    (entity, api) =%3E positionToCheck%0A  );%0A%7D%0A%0Afunction collisionConditional (schema) %7B%0A  return (entity, api, currentFrame) =%3E api.checkCollision(entity, currentFrame);%0A%7D%0A%0Afunction generateConditional (schema) %7B%0A  return _.sample(%5B%0A    positionConditional(schema),%0A    collisionConditional(schema)%0A  %5D);%0A%7D%0A%0A%0A
 // TODO 
@@ -1904,84 +1904,8 @@
 );%0A%0A
-  var randomX = getRandomInt(0, 600);%0A  var randomY = getRandomInt(0, 400);%0A
 %0A  v
@@ -2640,310 +2640,91 @@
     
-var attributeToCompare = randomAttribute(schema.getPosition.returns);%0A    var condition = compare(%0A      %5Bgt, lt%5D,%0A      function (entity, api) %7B return api.getPosition(entity)%5BattributeToCompare%5D; %7D,%0A      function (entity, api) %7B return _.sample(%5BrandomX, randomY%5D); %7D%0A    );%0A%0A    return (entity, api
+let condition = generateConditional(schema);%0A%0A    return (entity, api, currentFrame
 ) =%3E
@@ -2757,16 +2757,30 @@
 ity, api
+, currentFrame
 )) %7B%0A   

Refactor seeder if/else to use collsion as well as position