import vector

type Iterator = {
    reset->Void
    hasNext->Boolean
    get->T
    next->T}

type Vector = {
    size->Number
    isEmpty->Boolean
    clear->Void
    contains(_:T)->Boolean
    addFirst(_:T)->Void
    addLast(_:T)->Void
    firstElement->T
    lastElement->T
    removeFirst->T
    removeLast->T
    removeValue(_:T)->T
    indexOf(_:T)->Number
    at(_:Number)->T
    setValue(_:T)at(_:Number)->T
    add(_:T)at(_:Number)->Void
    removeFromIndex(_:Number)->T
    iterator->Iterator
    asString->String
    forEachDo(_:Block)->Void
    map(_:Block)->Vector
    ensureCapacity(_:Number)->Void
    capacity->Number
    copyInto(_)->Void
    indexOf(_:T)startingFrom(_:Number)->Number
    setSize(_:Number)->Void
    trimToSize->Void}

type Queue = {
    queue(_:T)->Void
    dequeue->T
    size->Number
    clear->Void
    isEmpty->Boolean
    iterator->Iterator
    asString->String}

method new->Queue is public{QueueVector.new(vector.defaultCapacity)}

method withSize(cap:Number)->Queue is public{QueueVector.new(cap)}

class QueueVector.new(capacity:Number){

    // Vector to maintain queue data
    var data:Vector is readable := vector.newWithSize(capacity)
    
    // @post value added to tail of queue
    // @param value the value to be added
    method queue(value)->Void is public{data.addLast(value)}

    // @pre queue not empty
    // @post head of queue removed and returned
    // @return value actually removed
    method dequeue->Dynamic is public{data.removeFromIndex(1)}

    // @post @return number of elements in queue
    method size->Number is public{data.size}

    // @post removes all elements from queue
    method clear->Void is public{data.clear}

    // @post @return true iff queue is empty
    method isEmpty->Boolean is public{data.isEmpty}

    // @post @return iterator to traverse queue
    method iterator->Iterator is public{data.iterator}

    // @post @return string representation of queue
    method asString->String is public{
        var str:String := "
            str := str ++ data.at(i)}
        return str ++ ">"}
}