import java.util.Vector;

/*
 * Created on May 10, 2004
 * @author kim
 * Elevator moves passengers from floor to floor in simulation.
 * Elevator has no smarts -- just runs up and down, stopping at each floor
 * without regard to demands from riders. 
 * It keeps running until told to shut down 
 */

public class Elevator extends Thread {
	private final String ELEVATOR_NAME;	// name of elevator
	private final int CAPACITY;			// number of people that will fit
	private int currentFloor;				// where elevator is now
	private boolean goingUp = true;     // true means elevator is going up
	private Building thisBuilding;		// Building containing elevator
	private long serviceTime;				// How long takes at each floor
	private long travelTime;				// How long it takes between floors
	private int numPassengers;				// number of passengers on elevator
	private Vector[] passengers;			// Names of passengers getting off at 
													// each floor.
	private int numberFloors;				// number of floors in building
	
	private boolean running = true;		// whether elevators are running
	
	public Elevator(String name, int numberOfFloors, int startingFloor,
			int capacity, Building office,
			long serviceTimeMS, long travelTimeMS) {
		ELEVATOR_NAME = name;
		numberFloors = numberOfFloors;
		currentFloor = startingFloor;
		thisBuilding = office;
		serviceTime = serviceTimeMS;
		travelTime = travelTimeMS;
		numPassengers = 0;
		CAPACITY = capacity;
	}

	// post:  stops elevator from running
	public void stopElevator() {
		running = false;
	}
	
	// post: returns floor where elevator is
	public synchronized int getCurrentFloor() {
		return currentFloor;
	}
	
	// run elevator up and down in building, picking up and depositing
	// passengers.
	public void run() {
		System.out.println(toString() + " starting");
		while (running) {
			System.out.println(toString()+" now on floor "+currentFloor
					+" at time "+ System.currentTimeMillis());

			// Should elevator change direction?
			if (currentFloor == numberFloors-1){
				goingUp = false;
			} else if (currentFloor == 0) {
				goingUp = true;
			}

			// tell passengers so they can exit or load
			notifyPassengers();
			thisBuilding.tellAt();
			try{
				// wait for passengers to leave and new ones to load
				sleep(serviceTime);		 
			} catch (InterruptedException exc) {
				System.out.println(toString() + " sleep interrupted");
			}
			System.out.println(toString() + " now leaving floor "+currentFloor
					+" at time "+ System.currentTimeMillis());
			
			// Go to next floor
			if (goingUp) {
				currentFloor++;
			} else {
				currentFloor--;
			}
			try{
				// wait for elevator to arrive at next floor
				sleep(travelTime);		 
			} catch (InterruptedException exc) {
				System.out.println(toString() + " sleep interrupted");
			}
		}
	}
	
	// post:  If elevator on currFloor and there is room for new passenger
	//        then return destFloor, otherwise return currFloor.
	public synchronized int takeElevator(int destFloor, int currFloor, 
			Person waiter) {
		if (currentFloor == currFloor && numPassengers < CAPACITY) {
			numPassengers++;
			System.out.println(waiter + " getting on " + toString() +
					" on floor " + currFloor+" at time "+ System.currentTimeMillis());
			while (currentFloor != destFloor){
				try{							// wait is in loop in case someone else sneaks in
					wait();
				} catch (InterruptedException ie){
					System.out.println(toString()+" interrupted: "+ie.toString());
				}
			}
			numPassengers--;
			return destFloor;
		} else {
			return currFloor;
		}
	}
	
	// post:  Woke up all passengers who may be waiting for elevator
	private synchronized void notifyPassengers(){
		notifyAll();
	}
	
	// post: return name of elevator
	public String toString(){
		return ELEVATOR_NAME;
	}
	
	public boolean isGoingUp(){
		return goingUp;
	}
}

