package ru.nsu.fit.evtushenko.storage;

import java.util.LinkedList;
import java.util.Observable;
import java.util.Queue;

public class Storage<T> extends Observable implements BlockingQueue<T> {
	private final int capacity;
	private final Object monitor = new Object();
	private final Queue<T> queue = new LinkedList<>();

	public Storage(int capacity) {
		this.capacity = capacity;
	}

	public Storage() {
		this.capacity = Integer.MAX_VALUE;
	}

	@Override
	public void add(T toAdd) throws InterruptedException {
		synchronized (monitor) {
			while (true) {
				if (queue.size() < capacity) {
					queue.add(toAdd);
					monitor.notifyAll();
					setChanged();
					notifyObservers(queue.size());
					return;
				} else {
					monitor.wait();
				}
			}
		}
	}

	@Override
	public T get() throws InterruptedException {
		synchronized (monitor) {
			while (true) {
				if (!queue.isEmpty()) {
					monitor.notifyAll();
					T result = queue.remove();
					setChanged();
					notifyObservers(queue.size());
					return result;
				} else {
					monitor.wait();
				}
			}
		}
	}

	@Override
	public int getSize() {
		synchronized (monitor) {
			return queue.size();
		}
	}
}