1 var define = require("../define").define,
  2         Collection = require("./Collection"),
  3         base = require("../base");
  4 
  5 /**
  6  * @class <p>FIFO Data structure</p>
  7  * @name Queue
  8  * @augments comb.collections.Collection
  9  * @memberOf comb.collections
 10  *
 11  * @property {Number} count the current number of elements in this queue
 12  * @property {Boolean} isEmpty true if this queue is empty
 13  * @property {Array} values a copy of the values contained in this queue
 14  */
 15 module.exports = exports = define(Collection, {
 16     instance : {
 17         /**@lends comb.collections.Queue.prototype*/
 18 
 19         constructor : function() {
 20             this.__queue = [];
 21             this.__next = 0;
 22             this.__last = 0;
 23         },
 24 
 25         /**
 26          * Add data to this queue
 27          * @param {*} data element to add
 28          */
 29         enqueue : function(data) {
 30             this.__queue[this.__last++] = data;
 31         },
 32 
 33         /**
 34          * Removes first item from the head of the queue
 35          *
 36          * @return {*} The element removed from this queue. Returns undefined if the queue is empty.
 37          */
 38         dequeue : function() {
 39             var ret = undefined,next = this.__next, queue;
 40             if (next != this.__last) {
 41                 queue = this.__queue;
 42                 ret = queue[next];
 43                 queue[this.__next++] = undefined;
 44             }
 45             return ret;
 46         },
 47 
 48         /**
 49          * Retrieves the item at the head of the queue without removing it
 50          *
 51          * @return {*} The element at the head of the queue. Returns undefined if the queue is empty.
 52          */
 53         peek : function() {
 54             var ret = undefined, next = this.__next;
 55             if (next != this.__last) {
 56                 ret = this.__queue[next];
 57             }
 58             return ret;
 59         },
 60 
 61         /**
 62          * Removes all items from this queue
 63          */
 64         clear : function() {
 65             this.__queue.length = 0;
 66             this.__next = 0;
 67             this.__last = 0;
 68         },
 69 
 70         /**
 71          * Determine if this queue contains the element
 72          * @param {*} obj the object to find
 73          *
 74          * @return {Boolean} true if this queue contains the element
 75          */
 76         contains : function(obj) {
 77             return this.__queue.indexOf(obj) != -1;
 78         },
 79         /**
 80          * Removes an element from this queue.
 81          * @param {*} obj the data to remove.
 82          *
 83          * @return {Boolean} true if the element was removed, false otherwise.
 84          */
 85         remove : function(obj) {
 86             var index = this.__queue.indexOf(obj), ret = false;
 87             if (index != -1) {
 88                 if (index == this.__next) {
 89                     this.dequeue();
 90                 } else {
 91                     this.__queue.splice(index, 1);
 92                     this.__last--;
 93                 }
 94                 ret = true;
 95             }
 96             return ret;
 97         },
 98 
 99         toString : function(){
100             return this.__queue.toString();
101         },
102 
103         getters : {
104 
105             count : function() {
106                 return this.__last - this.__next;
107             },
108 
109             isEmpty : function() {
110                 return this.__last - this.__next == 0;
111             },
112 
113             values : function() {
114                 return this.__queue.slice(this.__next, this.__last);
115             }
116         }
117     }
118 });