package edu.nyu.cs9053.concurrency.monitor;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * User: blangel
 * Date: 11/9/14
 * Time: 4:05 PM
 */
public class MonitorElevator implements Elevator {

    private final Lock monitor;

    private final Condition fullCondition;

    private final Condition emptyCondition;

    private int index;

    private final Object[] passengers;

    public MonitorElevator(int size) {
        this.passengers = new Object[size];
        this.index = 0;
        this.monitor = new ReentrantLock();
        this.fullCondition = monitor.newCondition();
        this.emptyCondition = monitor.newCondition();
    }

    @Override public void add(Object passenger) {
        monitor.lock();
        try {
            while (index == (passengers.length - 1)) {
                fullCondition.await();
            }
            System.out.printf("Added passenger%n");
            passengers[index++] = passenger;
            emptyCondition.signal();
        } catch (InterruptedException ie) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(ie);
        } finally {
            monitor.unlock();
        }
    }

    @Override public Object remove() {
        monitor.lock();
        try {
            while (index <= 0) {
                emptyCondition.await();
            }
            Object passenger = passengers[index];
            System.out.printf("Removed passenger%n");
            passengers[index--] = null;
            fullCondition.signal();
            return passenger;
        } catch (InterruptedException ie) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(ie);
        } finally {
            monitor.unlock();
        }
    }

}
