package org.academiadecodigo.bootcamp.concurrency.bqueue;

import java.util.LinkedList;
import java.util.Queue;

/**
 * Blocking Queue
 *
 * @param <T> the type of elements stored by this queue
 */
public class BQueue<T> {

    private Queue<T> queue;
    private int limit;

    /**
     * Constructs a new queue with a maximum size
     *
     * @param limit the queue size
     */
    public BQueue(int limit) {

        this.queue = new LinkedList<>();
        this.limit = limit;

    }

    /**
     * Inserts the specified element into the queue
     * Blocking operation if the queue is full
     *
     * @param data the data to add to the queue
     */
    public synchronized void offer(T data) {

        while (getSize() >= getLimit()) {
            try {
                System.out.println("waiting to offer");
                wait();
            } catch (InterruptedException e) {
            }
        }
        queue.offer(data);
        System.out.println("**** size is now " + queue.size());
        notifyAll();

    }

    /**
     * Retrieves and removes data from the head of the queue
     * Blocking operation if the queue is empty
     *
     * @return the data from the head of the queue
     */
    public synchronized T poll() {

        while (getSize() <= 0) {
            try {
                System.out.println("waiting to poll");
                wait();
            } catch (InterruptedException e) {
            }
        }
        T res = queue.poll();
        notifyAll();
        return res;
    }

    /**
     * Gets the number of elements in the queue
     *
     * @return the number of elements
     */
    public int getSize() {

        return queue.size();

    }

    /**
     * Gets the maximum number of elements that can be present in the queue
     *
     * @return the maximum number of elements
     */
    public int getLimit() {

        return limit;

    }

}
