import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class TrafficLightFrame extends JFrame {
	
    private TrafficLight aTrafficLight = new TrafficLight(); // This is the model

    // These are some components
    private JRadioButton[] 	buttons = new JRadioButton[3];
    private JButton  		advButton;
    private JProgressBar 	progressBar;
    private JSlider 		slider;
    private JComboBox  		actionList;
    private JCheckBox 		autoButton;
    private Timer  			aTimer;

	// We will need to disable this during an update, 
	// so we store it in an instance variable.
	private ActionListener	comboBoxListener;
	
    public TrafficLightFrame(String title) {
        super(title);
        buildWindow();
        
        // Add the Listeners
        for (int i=0; i<3; i++)
            buttons[i].addActionListener(new ActionListener() {
            	public void actionPerformed(ActionEvent e) {
            		handleRadioButtonPress((JRadioButton)e.getSource());
            	}
            });
            
		actionList.addActionListener(comboBoxListener = new ActionListener() {
        	public void actionPerformed(ActionEvent e) {
        		handleComboBoxSelection((JComboBox)e.getSource());
        	}
        });
        slider.addChangeListener(new ChangeListener() {
        	public void stateChanged(ChangeEvent e) {
        		handleSlider((JSlider)e.getSource());
        	}
        });
		autoButton.addActionListener(new ActionListener() {
        	public void actionPerformed(ActionEvent e) {
        		handleAutoButtonPress((JCheckBox)e.getSource());
        	}
        });
        advButton.addActionListener(new ActionListener() {
        	public void actionPerformed(ActionEvent e) {
        		handleAdvanceButtonPress();
        	}
        });
        
        // Add a timer for automode.  Set it to go off every 500 milliseconds
        aTimer = new Timer(500, new ActionListener() {
        	public void actionPerformed(ActionEvent e) {
        		handleTimerTick();
        	}
        });
        
        
        // Refresh the window
        update();

        
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(400, 250);
    }

    // Add all components to the frame's panel
    private void buildWindow() {
    	GridBagLayout 		layout = new GridBagLayout();
        GridBagConstraints 	constraints = new GridBagConstraints();
        setLayout(layout);

		// Add all the labels
        JLabel label = new JLabel("Manual");
        constraints.gridx = 0;
        constraints.gridy = 0;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        constraints.weightx = 0;
        constraints.weighty = 0;
        constraints.fill = GridBagConstraints.NONE;
        constraints.anchor = GridBagConstraints.NORTHWEST;
        constraints.insets = new Insets(5, 5, 0, 0);
        layout.setConstraints(label, constraints);
        add(label);
    	
        label = new JLabel("Action");
        constraints.gridx = 1;
        layout.setConstraints(label, constraints);
        add(label);
    	
        label = new JLabel("Advance");
        constraints.gridx = 2;
        layout.setConstraints(label, constraints);
        add(label);
    	
        label = new JLabel("Timer Progress");
        constraints.gridx = 0;
        constraints.gridy = 4;
        layout.setConstraints(label, constraints);
        add(label);
    	
    	// Add the Radio Buttons
        ButtonGroup lights = new ButtonGroup();
        JPanel aPanel = new JPanel(); 
        aPanel.setLayout(new BoxLayout(aPanel, BoxLayout.Y_AXIS));
        aPanel.setBackground(Color.black);          
        for (int i=0; i<3; i++) {
            buttons[i] = new JRadioButton("", false);
            buttons[i].setBackground(Color.black);
            lights.add(buttons[i]);
            aPanel.add(buttons[i]);
		}
        buttons[0].setText("Red");
        buttons[1].setText("Yellow");
        buttons[2].setText("Green");
        buttons[0].setForeground(Color.red);
        buttons[1].setForeground(Color.yellow);
        buttons[2].setForeground(Color.green);
		constraints.gridx = 0;
       	constraints.gridy = 1;
       	constraints.gridheight = 3;
        constraints.fill = GridBagConstraints.BOTH;
        layout.setConstraints(aPanel, constraints);
        add(aPanel);

        // Make the Actions List
        String[] actions = {"Stop", "Yield", "Go"};
        actionList = new JComboBox(actions);
        constraints.gridx = 1;
        constraints.gridy = 1;
        constraints.gridheight = 1;
        constraints.weightx = 1;
        constraints.fill = GridBagConstraints.HORIZONTAL;
        layout.setConstraints(actionList, constraints);
        add(actionList);
        
        // Make the Slider
        slider = new JSlider(JSlider.HORIZONTAL, 0, 20, 1);
        slider.setMajorTickSpacing(5);
		slider.setMinorTickSpacing(1);
		slider.setPaintTicks(true);
		slider.setPaintLabels(true);
        constraints.gridx = 1;
        constraints.gridy = 3;
        layout.setConstraints(slider, constraints);
        add(slider);
        
        // Add the auto checkbox button
        autoButton = new JCheckBox("Auto Advance");
        constraints.gridx = 1;
        constraints.gridy = 2;
        constraints.fill = GridBagConstraints.BOTH;
        layout.setConstraints(autoButton, constraints);
        add(autoButton);

        // Add the Advance Picture button
        advButton = new JButton(new ImageIcon("RedLight.jpg"));
        constraints.gridx = 2;
        constraints.gridy = 1;
        constraints.gridheight = 3;
        constraints.weightx = 0;
        constraints.weighty = 1;
        constraints.fill = GridBagConstraints.BOTH;
        constraints.insets = new Insets(5, 5, 0, 5);
        layout.setConstraints(advButton, constraints);
        add(advButton);

        // Add the progress bar
        progressBar = new JProgressBar(JProgressBar.HORIZONTAL, 0, 
        							   TrafficLight.MAX_TIME_COUNT);
        constraints.gridx = 0;
        constraints.gridy = 5;
        constraints.gridwidth = 3;
        constraints.gridheight = 1;
        constraints.weightx = 1;
        constraints.weighty = 2;
        constraints.fill = GridBagConstraints.BOTH;
        constraints.insets = new Insets(5, 5, 5, 5);
        layout.setConstraints(progressBar, constraints);
        add(progressBar);
    }

    // This is the Timer event handler
    private void handleTimerTick() {
		aTrafficLight.advanceTime();
        update();
    }

    // This is the Advance button event handler
    private void handleAdvanceButtonPress() {
        aTrafficLight.advanceState();
        update();
    }

    // This is the Auto button event handler
    private void handleAutoButtonPress(JCheckBox source) {
		if (source.isSelected())
            aTimer.start();
        else
            aTimer.stop();
        update();
    }

    // This is the radio button event handler
    private void handleRadioButtonPress(JRadioButton source) {
    	for (int i=0; i<3; i++) {
        	if (source == buttons[i])
            	aTrafficLight.setState(i+1);
		}
        update();
    }

    // The ComboBox Selection event handler
    private void handleComboBoxSelection(JComboBox source) {
        aTrafficLight.setState(source.getSelectedIndex() + 1);
        update();
    }
    
    // This is the Slider event handler
    private void handleSlider(JSlider source) {
        if (!source.getValueIsAdjusting()) {
        	int delay = source.getValue();
        	if (delay > 0) {
            	aTimer.setDelay(1000/delay);
            	if (aTimer.isRunning())
            		aTimer.restart();
            }
            else {
            	aTimer.setDelay(Integer.MAX_VALUE);
            }
            update();
        }
    }



    // Update the radio buttons according to the traffic light state
    private void updateRadioButtons() {
        for (int i=0; i<3; i++) {
            buttons[i].setSelected(aTrafficLight.getState() == (i+1));
        }
    }


    // Update the status pane according to the traffic light state
    private void updateAdvanceButton() {
    	String[] iconNames = {"RedLight.jpg","YellowLight.jpg","GreenLight.jpg"};
        advButton.setIcon(new ImageIcon(iconNames[aTrafficLight.getState()-1]));
    }
    

    // Update the combo box according to the traffic light state
    private void updateComboBox() {
        actionList.setSelectedIndex(aTrafficLight.getState() - 1);
    }


	// Update the progress bar
	private void updateProgressBar() {
		progressBar.setValue(aTrafficLight.getStateCount());
	}

    // Update all relevant components according to the traffic light state
    public void update() {
    	actionList.removeActionListener(comboBoxListener);
        updateRadioButtons();
        updateComboBox();
        updateAdvanceButton();
        updateProgressBar();
    	actionList.addActionListener(comboBoxListener);
    }


    public static void main(String args[]) {
        TrafficLightFrame frame =  new TrafficLightFrame("Traffic Light");
        frame.setVisible(true);
    }
}