import { ILoopFunction } from '@mezzy/function-types';
import List from './list';


export class Queue<T> {
    /**
     * Creates an empty queue.
     * @class A queue is a First-In-First-Out (FIFO) data structure, the first
     * element added to the queue will be the first one to be deleted. This
     * implementation uses a linked list as a container.
     * @constructor
     */
    constructor() { this._list = new List<T>(); }


    /**
     * List containing the elements.
     */
    private _list:List<T>;


    get isEmpty():boolean { return this._list.size <= 0; }
    get size():number { return this._list.size; }


    /**
     * Inserts the specified element into the end of this queue.
     * @param {Object} elem the element to insert.
     * @return {boolean} true if the element was inserted, or false if it is undefined.
     */
    add(elem:T):void { this._list.add(elem); }


    /**
     * Retrieves and removes the head of this queue.
     * @return {*} the head of this queue, or undefined if this queue is empty.
     */
    deleteFirst():T {
        if (this._list.size !== 0) {
            let item = this._list.first;
            this._list.deleteAtIndex(0);
            return item;
        }
        return undefined;
    }


    /**
     * Retrieves and removes the tail of this queue.
     * @return {*} the tail of this queue, or undefined if this queue is empty.
     */
    deleteLast():T {
        if (this._list.size !== 0) {
            let item = this._list.last;
            this._list.deleteAtIndex(this._list.size - 1);
            return item;
        }
        return undefined;
    }


    /**
     * Retrieves, but does not remove, the head of this queue.
     * @return {*} the head of this queue, or undefined if this queue is empty.
     */
    peek():T {
        if (this._list.size !== 0) return this._list.first;
        return undefined;
    }


    has(elem:T):boolean { return this._list.has(elem); }
    clear():void { this._list.clear(); }
    forEach(callback:ILoopFunction<T>) { this._list.forEach(callback); }
} // End class


export default Queue;
