/**
 * @overview Pool
 * @copyright Dreamlab Onet.pl sp. z. o o 2012
 */

/**
 * @class Pool
 * @classdoc Pool
 * 
 * @return {Pool}
 */
var Pool = function () {
    this._spareObjects = [];
    this._knownObjects = [];
    this._markedForDeletion = [];
    this._waitingCallbacks = [];
};

Pool.prototype = {};

/**
 * Delete all pool objects
 * @method
 * @return {undefined}
 */
Pool.prototype.clear = function () {
    this._spareObjects = [];
};

/**
 * Returns poll objects count
 * @method
 * @return {Number}
 */
Pool.prototype.getSpareLength = function () {
    return this._spareObjects.length;
};

/**
 * Returns waiting clients count
 * @method
 * @return {Number}
 */
Pool.prototype.getWaitingLength = function () {
    return this._waitingCallbacks.length;
};

/**
 * Mark all known objects for delayed deletion 
 * @method
 */
Pool.prototype.markForDeletion = function () {
    var obj, index;
    while ((obj = this._knownObjects.pop()) != undefined) {
        if ((index = this._spareObjects.indexOf(obj)) > -1 ) {
            this._spareObjects.splice(index, 1);
        }
        this._markedForDeletion.push(obj);
    }
};

/**
 * Add object to pool
 * @param {Object} object
 * @return {undefined}
 * @method
 */
Pool.prototype.add = function (object) {
    this._knownObjects.push(object);
    this.release(object);
};

/**
 * Return object to pool
 * @param {Object} object
 * @method
 */
Pool.prototype.release = function (object) {
    if (this._markedForDeletion.length > 0) {
        var index;
        if ((index = this._markedForDeletion.indexOf(object)) > -1) {
            this._markedForDeletion.splice(index, 1);
            return;
        }
    }
    if (this._waitingCallbacks.length > 0) {
        var callback = this._waitingCallbacks.shift();
        callback(object);
    } else {
        this._spareObjects.push(object);
    }
};

/**
 * Get object from pool
 * @param {Function} cb Will call cb(object) when object is available
 * @return {undefined}
 * @method
 */
Pool.prototype.get = function (cb) {
    if (this._spareObjects.length > 0) {
        var object = this._spareObjects.shift();
        cb(object);
    } else {
        this._waitingCallbacks.push(cb);
    }
};

exports.Pool = Pool;
