package junit.swingui;

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

import junit.framework.*;
import junit.runner.*;

/**
 * A test class selector. A simple dialog to pick the name of a test suite.
 */
class TestSelector extends JDialog {
	private JButton fCancel;
	private JButton fOk;
	private JList fList;
	private JScrollPane fScrolledList;
	private JLabel fDescription;
	private String fSelectedItem;
	
	/**
	 * Renders TestFailures in a JList
	 */
	static class TestCellRenderer extends DefaultListCellRenderer {
		Icon fLeafIcon;
		Icon fSuiteIcon;
		
		public TestCellRenderer() {
			fLeafIcon= UIManager.getIcon("Tree.leafIcon");
			fSuiteIcon= UIManager.getIcon("Tree.closedIcon");
		}
		
		public Component getListCellRendererComponent(
				JList list, Object value, int modelIndex, 
				boolean isSelected, boolean cellHasFocus) {
			Component c= super.getListCellRendererComponent(list, value, modelIndex, isSelected, cellHasFocus);
			String displayString= displayString((String)value);
			
			if (displayString.startsWith("AllTests"))
				setIcon(fSuiteIcon);
			else
				setIcon(fLeafIcon);
				
			setText(displayString);
		    	return c;
		}
		
		public static String displayString(String className) {
			int typeIndex= className.lastIndexOf('.');
    			if (typeIndex < 0) 
    				return className;
    			return className.substring(typeIndex+1) + " - " + className.substring(0, typeIndex);
		}
		
		public static boolean matchesKey(String s, char ch) {
    			return ch == Character.toUpperCase(s.charAt(typeIndex(s)));
		}
		
		private static int typeIndex(String s) {
			int typeIndex= s.lastIndexOf('.');
			int i= 0;
    			if (typeIndex > 0) 
    				i= typeIndex+1;
    			return i;
		}
	}
	
	protected class DoubleClickListener extends MouseAdapter {
		public void mouseClicked(MouseEvent e) {
	    		if (e.getClickCount() == 2) {
	    			okSelected();
	    		}
	      }
	}
	
	protected class KeySelectListener extends KeyAdapter {
		public void keyTyped(KeyEvent e) {
			keySelectTestClass(e.getKeyChar());
		}
	}

	public TestSelector(Frame parent, TestCollector testCollector) {
		super(parent, true);
		setSize(350, 300);
		setResizable(false);
		setLocationRelativeTo(parent);
		setTitle("Test Selector");
		
		Vector list= null;
		try {
			parent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
			list= createTestList(testCollector);
		} finally {
			parent.setCursor(Cursor.getDefaultCursor());
		}
		fList= new JList(list);
		fList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		fList.setCellRenderer(new TestCellRenderer());
		fScrolledList= new JScrollPane(fList);

		fCancel= new JButton("Cancel");
		fDescription= new JLabel("Select the Test class:");
		fOk= new JButton("OK");
		fOk.setEnabled(false);
		getRootPane().setDefaultButton(fOk);
		
		defineLayout();
		addListeners();
	}
	
	private void addListeners() {
		fCancel.addActionListener(
			new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					dispose();
				}
			}
		);
		
		fOk.addActionListener(
			new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					okSelected();
				}
			}
		);

		fList.addMouseListener(new DoubleClickListener());
		fList.addKeyListener(new KeySelectListener());
		fList.addListSelectionListener(
			new ListSelectionListener() {
				public void valueChanged(ListSelectionEvent e) {
					checkEnableOK(e);
				}
			}
		);

		addWindowListener(
			new WindowAdapter() {
				public void windowClosing(WindowEvent e) {
					dispose();
				}
			}
		);
	}
	
	private void defineLayout() {
		getContentPane().setLayout(new GridBagLayout());
		GridBagConstraints labelConstraints = new GridBagConstraints();
		labelConstraints.gridx= 0; labelConstraints.gridy= 0;
		labelConstraints.gridwidth= 1; labelConstraints.gridheight= 1;
		labelConstraints.fill= GridBagConstraints.BOTH;
		labelConstraints.anchor= GridBagConstraints.WEST;
		labelConstraints.weightx= 1.0;
		labelConstraints.weighty= 0.0;
		labelConstraints.insets= new Insets(8, 8, 0, 8);
		getContentPane().add(fDescription, labelConstraints);

		GridBagConstraints listConstraints = new GridBagConstraints();
		listConstraints.gridx= 0; listConstraints.gridy= 1;
		listConstraints.gridwidth= 4; listConstraints.gridheight= 1;
		listConstraints.fill= GridBagConstraints.BOTH;
		listConstraints.anchor= GridBagConstraints.CENTER;
		listConstraints.weightx= 1.0;
		listConstraints.weighty= 1.0;
		listConstraints.insets= new Insets(8, 8, 8, 8);
		getContentPane().add(fScrolledList, listConstraints);
		
		GridBagConstraints okConstraints= new GridBagConstraints();
		okConstraints.gridx= 2; okConstraints.gridy= 2;
		okConstraints.gridwidth= 1; okConstraints.gridheight= 1;
		okConstraints.anchor= java.awt.GridBagConstraints.EAST;
		okConstraints.insets= new Insets(0, 8, 8, 8);
		getContentPane().add(fOk, okConstraints);


		GridBagConstraints cancelConstraints = new GridBagConstraints();
		cancelConstraints.gridx= 3; cancelConstraints.gridy= 2;
		cancelConstraints.gridwidth= 1; cancelConstraints.gridheight= 1;
		cancelConstraints.anchor= java.awt.GridBagConstraints.EAST;
		cancelConstraints.insets= new Insets(0, 8, 8, 8);
		getContentPane().add(fCancel, cancelConstraints);
	}
	
	public void checkEnableOK(ListSelectionEvent e) {
		fOk.setEnabled(fList.getSelectedIndex() != -1);
	}
	
	public void okSelected() {
		fSelectedItem= (String)fList.getSelectedValue();
		dispose();
	}
	
	public boolean isEmpty() {
		return fList.getModel().getSize() == 0;
	}
	
	public void keySelectTestClass(char ch) {
		ListModel model= fList.getModel();
		if (!Character.isJavaIdentifierStart(ch))
			return;
		for (int i= 0; i < model.getSize(); i++) {
			String s= (String)model.getElementAt(i);
			if (TestCellRenderer.matchesKey(s, Character.toUpperCase(ch))) {
				fList.setSelectedIndex(i);
				fList.ensureIndexIsVisible(i);
				return;
			}
		}
		Toolkit.getDefaultToolkit().beep();
	}
	
	public String getSelectedItem() {
		return fSelectedItem;
	}

	private Vector createTestList(TestCollector collector) {
    		Enumeration each= collector.collectTests();
    		Vector v= new Vector(200);
    		Vector displayVector= new Vector(v.size());
    		while(each.hasMoreElements()) {
    			String s= (String)each.nextElement();
    			v.addElement(s);
    			displayVector.addElement(TestCellRenderer.displayString(s));
    		}
    		if (v.size() > 0)
    			Sorter.sortStrings(displayVector, 0, displayVector.size()-1, new ParallelSwapper(v));
    		return v;
	}
	
	private class ParallelSwapper implements Sorter.Swapper {
		Vector fOther;
		
		ParallelSwapper(Vector other) {
			fOther= other;
		}
		public void swap(Vector values, int left, int right) {
			Object tmp= values.elementAt(left); 
			values.setElementAt(values.elementAt(right), left); 
			values.setElementAt(tmp, right);
			Object tmp2= fOther.elementAt(left);
			fOther.setElementAt(fOther.elementAt(right), left);
			fOther.setElementAt(tmp2, right);
		}			
	}
}