import java.util.ArrayList;
public class TrafficLight implements Subject {
	// The longest amount of time that the traffic light will 
	// remain in a particular state.   This can be used by a 
	// progress bar if necessary
	public static final int  MAX_TIME_COUNT = 8;
	
	private int  currentState;  // 1=red, 2=yellow, 3=green
    private int	 stateCount;	// amount of time in this state
    
    ArrayList<Observer>     observers = new ArrayList<Observer>();

    // Constructor that makes a red traffic light
    public TrafficLight() {
        currentState = 1;
        stateCount = 0;
    }

    // Advance the traffic light to the next state
    public int advanceState() {
        currentState = ++currentState % 3 + 1;
        stateCount = 0;
        updateObservers(); // Tell the observer applications about this change
        return currentState; 
    } 

    // Simulate a single time unit of time passing by
    public void advanceTime() {
		// The number of seconds (i.e., time units) that 
		// the traffic light remains in each state
    	int[] stateTimes = {6, 3, 8};
    	
    	// advance the time spent in the current state
    	stateCount++;
    	updateObservers(); // Tell the observer applications about this change
    	
        // Check if we have reached time limit for current state
        if (stateCount > stateTimes[currentState-1])
	        advanceState(); 
    } 

    // Return the amount of time spent in the current state 
    public int getStateCount() {
        return stateCount; 
    } 

    // Return the state of the traffic light (as a number from 1 to 3) 
    public int getState() {
        return currentState; 
    } 

    // Set the state of the traffic light (as a number from 1 to 3) 
    // If the integer is out of range, do nothing 
    public void setState(int newState) {
        if ((newState > 0) && (newState <4)) {
            currentState = newState; 
            stateCount = 0;
            updateObservers(); // Tell the observer applications about this change
        }
    } 
  
    // Return a string representation of the traffic light
    public String toString() {
    	String[] colours = {"Red", "Yellow", "Green"}; 
        return colours[currentState] + " Traffic Light";
    }
    
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    public void unregisterObserver(Observer observer) {
        observers.remove(observer);
    }

    // This method is called whenever there is a change to the model.
    // It informs all registered observer applications of the change.
    private void updateObservers() {
        for (Observer anObserver: observers)
            anObserver.update();
    } 
} 
