var _ = require('underscore');

var config = require('./config');

function Queue(tasks, ctx, onTask) {
  this.tasks = _.clone(tasks) || [];
  this.ctx = ctx || {};
  this.onTask = onTask;
  this.error = null;
}

Queue.prototype.addTask = function(task) {
  this.tasks.push(task);
  return this;
};

Queue.prototype.addTasks = function(tasks) {
  this.tasks = this.tasks.concat(tasks);
  return this;
};

Queue.prototype.run = function(concurrency, onDone) {
  this.concurrency = concurrency || config.network.concurrency || 1;
  this.onDone = onDone;

  var self = this;
  for (var i = 0; i < this.concurrency; ++i) {
    setImmediate(function() { self.workerRun(); });
  }
};

Queue.prototype.workerRun = function() {
  // no more tasks, quit now
  if (this.tasks.length === 0) {
    if (--this.concurrency === 0 && this.onDone)
      this.onDone(this.error, this.ctx);
    return;
  }

  var task = this.tasks.shift();
  var self = this;
  this.onTask(task, self, function(e) {
    if (e) self.error = e;

    // TODO: could retry failed task here.
    setImmediate(function() { self.workerRun(); });
  });
};

module.exports = Queue;