package junit.swingui;

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

import java.util.*;
import java.lang.reflect.*;
import java.text.NumberFormat;
import java.net.URL;
import java.io.*;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;

/**
 * A Swing based user interface to run tests.
 * Enter the name of a class which either provides a static
 * suite method or is a subclass of TestCase.
 * <pre>
 * Synopsis: java junit.swingui.TestRunner [-noloading] [TestCase]
 * </pre>
 * TestRunner takes as an optional argument the name of the testcase class to be run.
 */
public class TestRunner extends BaseTestRunner implements TestRunContext {
	protected JFrame fFrame;
	private Thread fRunner;
	private TestResult fTestResult;
	
	private JComboBox fSuiteCombo;
	private ProgressBar fProgressIndicator;
	private DefaultListModel fFailures;
	private JLabel fLogo;
	private CounterPanel fCounterPanel;
	private JButton fRun;
	private JButton fQuitButton;
	private JButton fRerunButton;
	private StatusLine fStatusLine;
	private FailureDetailView fFailureView;
	private JTabbedPane fTestViewTab;
	private JCheckBox fUseLoadingRunner;
	private Vector fTestRunViews= new Vector(); // view associated with tab in tabbed pane
	private static Font PLAIN_FONT= StatusLine.PLAIN_FONT;
	private static Font BOLD_FONT= StatusLine.BOLD_FONT;
	private static final int GAP= 4;
	private static final int HISTORY_LENGTH= 5;

	private static final String TESTCOLLECTOR_KEY= "TestCollectorClass";
	private static final String FAILUREDETAILVIEW_KEY= "FailureViewClass";
		
	public TestRunner() {
	} 
	
	public static void main(String[] args) {
		new TestRunner().start(args);
	}
	 
	public static void run(Class test) {
		String args[]= { test.getName() };
		main(args);
	}
	
	public void addError(final Test test, final Throwable t) {
		SwingUtilities.invokeLater(
			new Runnable() {
				public void run() {
					fCounterPanel.setErrorValue(fTestResult.errorCount());
					appendFailure("Error", test, t);
				}
			}
		);
	}
	
	public void addFailure(final Test test, final AssertionFailedError t) {
		SwingUtilities.invokeLater(
			new Runnable() {
				public void run() {
					fCounterPanel.setFailureValue(fTestResult.failureCount());
					appendFailure("Failure", test, t);
				}
			}		
		);
	}
	
	public void startTest(Test test) {
		postInfo("Running: "+test);
	}
	
	public void endTest(Test test) {
		postEndTest(test);
	}

	private void postEndTest(final Test test) {
		synchUI();
		SwingUtilities.invokeLater(
			new Runnable() {
				public void run() {
					if (fTestResult != null) {
						fCounterPanel.setRunValue(fTestResult.runCount());
						fProgressIndicator.step(fTestResult.wasSuccessful());
					}
				}
			}
		);
	}

	public void setSuite(String suiteName) {
		fSuiteCombo.getEditor().setItem(suiteName);
	}

	private void addToHistory(final String suite) {
		for (int i= 0; i < fSuiteCombo.getItemCount(); i++) {
			if (suite.equals(fSuiteCombo.getItemAt(i))) {
				fSuiteCombo.removeItemAt(i);
				fSuiteCombo.insertItemAt(suite, 0);
				fSuiteCombo.setSelectedIndex(0);
				return;
			}
		}
		fSuiteCombo.insertItemAt(suite, 0);
		fSuiteCombo.setSelectedIndex(0);
		pruneHistory();
	}
	
	private void pruneHistory() {
		int historyLength= getPreference("maxhistory", HISTORY_LENGTH);
		if (historyLength < 1)
			historyLength= 1;
		for (int i= fSuiteCombo.getItemCount()-1; i > historyLength-1; i--) 
			fSuiteCombo.removeItemAt(i);
	}
	
	private void appendFailure(String kind, Test test, Throwable t) {
		fFailures.addElement(new TestFailure(test, t));
		if (fFailures.size() == 1) 
			revealFailure(test);
	}
	
	private void revealFailure(Test test) {
		for (Enumeration e= fTestRunViews.elements(); e.hasMoreElements(); ) {
			TestRunView v= (TestRunView) e.nextElement();
			v.revealFailure(test);
		}
	}
		
	protected void aboutToStart(final Test testSuite) {
		for (Enumeration e= fTestRunViews.elements(); e.hasMoreElements(); ) {
			TestRunView v= (TestRunView) e.nextElement();
			v.aboutToStart(testSuite, fTestResult);
		}
	}
	
	protected void runFinished(final Test testSuite) {
		SwingUtilities.invokeLater(
			new Runnable() {
				public void run() {
					for (Enumeration e= fTestRunViews.elements(); e.hasMoreElements(); ) {
						TestRunView v= (TestRunView) e.nextElement();
						v.runFinished(testSuite, fTestResult);
					}
				}
			}
		);
	}

	protected CounterPanel createCounterPanel() {
		return new CounterPanel();
	}
	
	protected JPanel createFailedPanel() {
		JPanel failedPanel= new JPanel(new GridLayout(0, 1, 0, 2));
		fRerunButton= new JButton("Run");
		fRerunButton.setEnabled(false);
		fRerunButton.addActionListener(
			new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					rerun();
				}
			}
		);
		failedPanel.add(fRerunButton);
		return failedPanel;
	}
			
	protected FailureDetailView createFailureDetailView() {
		String className= BaseTestRunner.getPreference(FAILUREDETAILVIEW_KEY);
		if (className != null) {			
			Class viewClass= null;
			try {
				viewClass= Class.forName(className);
				return (FailureDetailView)viewClass.newInstance();
			} catch(Exception e) {
				JOptionPane.showMessageDialog(fFrame, "Could not create Failure DetailView - using default view");
			}
		}
		return new DefaultFailureDetailView();
	}

	/**
	 * Creates the JUnit menu. Clients override this
	 * method to add additional menu items.
	 */
	protected JMenu createJUnitMenu() {
		JMenu menu= new JMenu("JUnit");
		menu.setMnemonic('J');
		JMenuItem mi1= new JMenuItem("About...");
		mi1.addActionListener(
		    new ActionListener() {
		        public void actionPerformed(ActionEvent event) {
		            about();
		        }
		    }
		);
		mi1.setMnemonic('A');
		menu.add(mi1);
		
		menu.addSeparator();
		JMenuItem mi2= new JMenuItem(" Exit ");
		mi2.addActionListener(
		    new ActionListener() {
		        public void actionPerformed(ActionEvent event) {
		            terminate();
		        }
		    }
		);
		mi2.setMnemonic('x');
		menu.add(mi2);

		return menu;
	}
	
	protected JFrame createFrame(String title) {
		JFrame frame= new JFrame("JUnit");
		Image icon= loadFrameIcon();	
		if (icon != null)
			frame.setIconImage(icon);
		frame.getContentPane().setLayout(new BorderLayout(0, 0));
		
		frame.addWindowListener(
			new WindowAdapter() {
				public void windowClosing(WindowEvent e) {
					terminate();
				}
			}
		);
		return frame;
	}
	
	protected JLabel createLogo() {
		JLabel label;
		Icon icon= getIconResource(BaseTestRunner.class, "logo.gif");
		if (icon != null) 
			label= new JLabel(icon);
		else
			label= new JLabel("JV");
		label.setToolTipText("JUnit Version "+Version.id());
		return label;
	}
	
	protected void createMenus(JMenuBar mb) {
		mb.add(createJUnitMenu());
	}
		
	protected JCheckBox createUseLoaderCheckBox() {
		boolean useLoader= useReloadingTestSuiteLoader();
		JCheckBox box= new JCheckBox("Reload classes every run", useLoader);
		box.setToolTipText("Use a custom class loader to reload the classes for every run");
		if (inVAJava())
			box.setVisible(false);
		return box;
	}
	
	protected JButton createQuitButton() {
		 // spaces required to avoid layout flicker
		 // Exit is shorter than Stop that shows in the same column
		JButton quit= new JButton(" Exit "); 
		quit.addActionListener(
			new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					terminate();
				}
			}
		);
		return quit;
	}
	
	protected JButton createRunButton() {
		JButton run= new JButton("Run");
		run.setEnabled(true);
		run.addActionListener(
			new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					runSuite();
				}
			}
		);
		return run;
	}
	
	protected Component createBrowseButton() {
		JButton browse= new JButton("...");
		browse.setToolTipText("Select a Test class");
		browse.addActionListener(
			new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					browseTestClasses();
				}
			}
		);
		return browse;		
	}
	
	protected StatusLine createStatusLine() {
		return new StatusLine(420);
	}
	
	protected JComboBox createSuiteCombo() {
		JComboBox combo= new JComboBox();
		combo.setEditable(true);
		combo.setLightWeightPopupEnabled(false);
		
		combo.getEditor().getEditorComponent().addKeyListener(
			new KeyAdapter() {
				public void keyTyped(KeyEvent e) {
					textChanged();
					if (e.getKeyChar() == KeyEvent.VK_ENTER)
						runSuite();
				}
			}
		);
		try {
			loadHistory(combo);
		} catch (IOException e) {
			// fails the first time
		}
		combo.addItemListener(
			new ItemListener() {
				public void itemStateChanged(ItemEvent event) {
					if (event.getStateChange() == ItemEvent.SELECTED) {
						textChanged();
					}
				}
			}
		);
		return combo;
	}
	
	protected JTabbedPane createTestRunViews() {
		JTabbedPane pane= new JTabbedPane(JTabbedPane.BOTTOM);

		FailureRunView lv= new FailureRunView(this);
		fTestRunViews.addElement(lv);
		lv.addTab(pane);
		
		TestHierarchyRunView tv= new TestHierarchyRunView(this);
		fTestRunViews.addElement(tv);
		tv.addTab(pane);
		
		pane.addChangeListener(
			new ChangeListener() {
				public void stateChanged(ChangeEvent e) {
					testViewChanged();
				}
			}
		);
		return pane;
	}
	
	public void testViewChanged() {
		TestRunView view= (TestRunView)fTestRunViews.elementAt(fTestViewTab.getSelectedIndex());
		view.activate();
	}
	
	protected TestResult createTestResult() {
		return new TestResult();
	}
	
	protected JFrame createUI(String suiteName) {	
		JFrame frame= createFrame("JUnit");	
		JMenuBar mb= new JMenuBar();
		createMenus(mb);
		frame.setJMenuBar(mb);
	
		JLabel suiteLabel= new JLabel("Test class name:");
		fSuiteCombo= createSuiteCombo();
		fRun= createRunButton();
		frame.getRootPane().setDefaultButton(fRun);
		Component browseButton= createBrowseButton();
		
		fUseLoadingRunner= createUseLoaderCheckBox();
		fProgressIndicator= new ProgressBar();
		fCounterPanel= createCounterPanel();
		
		JLabel failureLabel= new JLabel("Errors and Failures:");
		fFailures= new DefaultListModel();
		
		fTestViewTab= createTestRunViews();	
		JPanel failedPanel= createFailedPanel();
		
		fFailureView= createFailureDetailView();
		JScrollPane tracePane= new JScrollPane(fFailureView.getComponent(), JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

		fStatusLine= createStatusLine();
		fQuitButton= createQuitButton();
		fLogo= createLogo();
					
		JPanel panel= new JPanel(new GridBagLayout());
	
		addGrid(panel, suiteLabel,	0, 0, 2, GridBagConstraints.HORIZONTAL, 	1.0, GridBagConstraints.WEST);
		addGrid(panel, fSuiteCombo, 	0, 1, 1, GridBagConstraints.HORIZONTAL, 	1.0, GridBagConstraints.WEST);
		addGrid(panel, browseButton, 	1, 1, 1, GridBagConstraints.NONE, 			0.0, GridBagConstraints.WEST);
		addGrid(panel, fRun, 		2, 1, 1, GridBagConstraints.HORIZONTAL, 	0.0, GridBagConstraints.CENTER);

		addGrid(panel, fUseLoadingRunner,  	0, 2, 3, GridBagConstraints.HORIZONTAL, 1.0, GridBagConstraints.WEST);
		addGrid(panel, new JSeparator(), 	0, 3, 3, GridBagConstraints.HORIZONTAL, 1.0, GridBagConstraints.WEST);

		
		addGrid(panel, fProgressIndicator, 	0, 4, 2, GridBagConstraints.HORIZONTAL, 	1.0, GridBagConstraints.WEST);
		addGrid(panel, fLogo, 			2, 4, 1, GridBagConstraints.NONE, 			0.0, GridBagConstraints.NORTH);

		addGrid(panel, fCounterPanel,	 0, 5, 2, GridBagConstraints.NONE, 			0.0, GridBagConstraints.CENTER);

		JSplitPane splitter= new JSplitPane(JSplitPane.VERTICAL_SPLIT, fTestViewTab, tracePane);
		addGrid(panel, splitter, 	 0, 6, 2, GridBagConstraints.BOTH, 			1.0, GridBagConstraints.WEST);				

		addGrid(panel, failedPanel, 	 2, 6, 1, GridBagConstraints.HORIZONTAL, 	0.0, GridBagConstraints.NORTH/*CENTER*/);
		
		addGrid(panel, fStatusLine, 	 0, 8, 2, GridBagConstraints.HORIZONTAL, 	1.0, GridBagConstraints.CENTER);
		addGrid(panel, fQuitButton, 	 2, 8, 1, GridBagConstraints.HORIZONTAL, 	0.0, GridBagConstraints.CENTER);
		
		frame.setContentPane(panel);
		frame.pack();
		frame.setLocation(200, 200);
		return frame;
	}

	private void addGrid(JPanel p, Component co, int x, int y, int w, int fill, double wx, int anchor) {
		GridBagConstraints c= new GridBagConstraints();
		c.gridx= x; c.gridy= y;
		c.gridwidth= w;
		c.anchor= anchor;
		c.weightx= wx;
		c.fill= fill;
		if (fill == GridBagConstraints.BOTH || fill == GridBagConstraints.VERTICAL)
			c.weighty= 1.0;
		c.insets= new Insets(y == 0 ? GAP : 0, x == 0 ? GAP : 0, GAP, GAP);
		p.add(co, c);
	}

	protected String getSuiteText() {
		if (fSuiteCombo == null)
			return "";
		return (String)fSuiteCombo.getEditor().getItem();
	}
	
	public ListModel getFailures() {
		return fFailures;
	}
	
	public void insertUpdate(DocumentEvent event) {
		textChanged();
	}
		
	public void browseTestClasses() {
		TestCollector collector= createTestCollector();		
		TestSelector selector= new TestSelector(fFrame, collector);
		if (selector.isEmpty()) {
			JOptionPane.showMessageDialog(fFrame, "No Test Cases found.\nCheck that the configured \'TestCollector\' is supported on this platform.");
			return;
		}
		selector.show();
		String className= selector.getSelectedItem();
		if (className != null)
			setSuite(className);
	}

	TestCollector createTestCollector() {
		String className= BaseTestRunner.getPreference(TESTCOLLECTOR_KEY);
		if (className != null) {			
			Class collectorClass= null;
			try {
				collectorClass= Class.forName(className);
				return (TestCollector)collectorClass.newInstance();
			} catch(Exception e) {
				JOptionPane.showMessageDialog(fFrame, "Could not create TestCollector - using default collector");
			}
		}
		return new SimpleTestCollector();
	}
	
	private Image loadFrameIcon() {
		ImageIcon icon= (ImageIcon)getIconResource(BaseTestRunner.class, "smalllogo.gif");
		if (icon != null)
			return icon.getImage();
		return null;
	}
	
	private void loadHistory(JComboBox combo) throws IOException {
		BufferedReader br= new BufferedReader(new FileReader(getSettingsFile()));
		int itemCount= 0;
		try {
			String line;
			while ((line= br.readLine()) != null) {
				combo.addItem(line);
				itemCount++;
			}
			if (itemCount > 0)
				combo.setSelectedIndex(0);

		} finally {
			br.close();
		}
	}
	
	private File getSettingsFile() {
	 	String home= System.getProperty("user.home");
 		return new File(home,".junitsession");
 	}
	
	private void postInfo(final String message) {
		SwingUtilities.invokeLater(
			new Runnable() {
				public void run() {
					showInfo(message);
				}
			}
		);
	}
	
	private void postStatus(final String status) {
		SwingUtilities.invokeLater(
			new Runnable() {
				public void run() {
					showStatus(status);
				}
			}
		);
	}
	
	public void removeUpdate(DocumentEvent event) {
		textChanged();
	}
	
	private void rerun() {
		TestRunView view= (TestRunView)fTestRunViews.elementAt(fTestViewTab.getSelectedIndex());
		Test rerunTest= view.getSelectedTest();
		if (rerunTest != null)
			rerunTest(rerunTest);
	}
	
	private void rerunTest(Test test) {
		if (!(test instanceof TestCase)) {
			showInfo("Could not reload "+ test.toString());
			return;
		}
		Test reloadedTest= null;
		try {
			Class reloadedTestClass= getLoader().reload(test.getClass());
			Class[] classArgs= { String.class };
			Object[] args= new Object[]{((TestCase)test).getName()};
			Constructor constructor= reloadedTestClass.getConstructor(classArgs);
			reloadedTest=(Test)constructor.newInstance(args);
		} catch(Exception e) {
			showInfo("Could not reload "+ test.toString());
			return;
		}
		TestResult result= new TestResult();
		reloadedTest.run(result);
		
		String message= reloadedTest.toString();
		if(result.wasSuccessful())
			showInfo(message+" was successful");
		else if (result.errorCount() == 1) 
			showStatus(message+" had an error"); 
		else 
			showStatus(message+" had a failure");
	}

	protected void reset() {
		fCounterPanel.reset();
		fProgressIndicator.reset();
		fRerunButton.setEnabled(false);
		fFailureView.clear();
		fFailures.clear();
	}
	
	/**
	 * runs a suite.
	 * @deprecated use runSuite() instead
	 */
	public void run() {
		runSuite();
	}
	
	protected void runFailed(String message) {
		showStatus(message);
		fRun.setText("Run");
		fRunner= null;
	}
	
	synchronized public void runSuite() {
		if (fRunner != null) {
			fTestResult.stop();
		} else {
			setLoading(shouldReload());
			reset();
			showInfo("Load Test Case...");
			final String suiteName= getSuiteText();
			final Test testSuite= getTest(suiteName);		
			if (testSuite != null) {
				addToHistory(suiteName);
				doRunTest(testSuite);
			}
		}
	}
	
	private boolean shouldReload() {
		return !inVAJava() && fUseLoadingRunner.isSelected();
	}
	

	synchronized protected void runTest(final Test testSuite) {
		if (fRunner != null) {
			fTestResult.stop();
		} else {
			reset();	
			if (testSuite != null) {
				doRunTest(testSuite);
			}
		}
	}
	
	private void doRunTest(final Test testSuite) {
		setButtonLabel(fRun, "Stop");
		fRunner= new Thread("TestRunner-Thread") {
			public void run() {
				TestRunner.this.start(testSuite); 
				postInfo("Running...");
				
				long startTime= System.currentTimeMillis();
				testSuite.run(fTestResult);
					
				if (fTestResult.shouldStop()) {
					postStatus("Stopped");
				} else {
					long endTime= System.currentTimeMillis();
					long runTime= endTime-startTime;
					postInfo("Finished: " + elapsedTimeAsString(runTime) + " seconds");
				}
				runFinished(testSuite);
				setButtonLabel(fRun, "Run");
				fRunner= null;
				System.gc();
			}
		};
		// make sure that the test result is created before we start the
		// test runner thread so that listeners can register for it.
		fTestResult= createTestResult();
		fTestResult.addListener(TestRunner.this);
		aboutToStart(testSuite);

		fRunner.start();
	}

	private void saveHistory() throws IOException {
		BufferedWriter bw= new BufferedWriter(new FileWriter(getSettingsFile()));
		try {
			for (int i= 0; i < fSuiteCombo.getItemCount(); i++) {
				String testsuite= fSuiteCombo.getItemAt(i).toString();
				bw.write(testsuite, 0, testsuite.length());
				bw.newLine();
			}
		} finally {
			bw.close();
		}
	}
	
	private void setButtonLabel(final JButton button, final String label) {
		SwingUtilities.invokeLater(
			new Runnable() {
				public void run() {
					button.setText(label);
				}
			}
		);
	}
	
	private void setLabelValue(final JTextField label, final int value) {
		SwingUtilities.invokeLater(
			new Runnable() {
				public void run() {
					label.setText(Integer.toString(value));
				}
			}
		);
	}
		
	public void handleTestSelected(Test test) {
		fRerunButton.setEnabled(test != null && (test instanceof TestCase));
		showFailureDetail(test);
	}

	private void showFailureDetail(Test test) {
		if (test != null) {
			ListModel failures= getFailures();
			for (int i= 0; i < failures.getSize(); i++) {
				TestFailure failure= (TestFailure)failures.getElementAt(i);
				if (failure.failedTest() == test) {
					fFailureView.showFailure(failure);
					return;
				}
			}
		}
		fFailureView.clear();
	}
		
	private void showInfo(String message) {
		fStatusLine.showInfo(message);
	}
	
	private void showStatus(String status) {
		fStatusLine.showError(status);
	}
	
	/**
	 * Starts the TestRunner
	 */
	public void start(String[] args) {		
		String suiteName= processArguments(args);
		fFrame= createUI(suiteName);
		fFrame.pack(); 
		fFrame.setVisible(true);

		if (suiteName != null) {
			setSuite(suiteName);
			runSuite();
		}
	}
		
	private void start(final Test test) {
		SwingUtilities.invokeLater(
			new Runnable() {
				public void run() {
					int total= test.countTestCases();
					fProgressIndicator.start(total);
					fCounterPanel.setTotal(total);
				}
			}
		);
	}
	
	/**
	 * Wait until all the events are processed in the event thread
	 */
	private void synchUI() {
		try {
			SwingUtilities.invokeAndWait(
				new Runnable() {
					public void run() {}
				}		
			);
		}
		catch (Exception e) {
		}
	}
	
	/**
	 * Terminates the TestRunner
	 */
	public void terminate() {
		fFrame.dispose();
		try {
			saveHistory();
		} catch (IOException e) {
			System.out.println("Couldn't save test run history");
		}
		System.exit(0);
	}
	
	public void textChanged() {
		fRun.setEnabled(getSuiteText().length() > 0);
		clearStatus();
	}
	
	protected void clearStatus() {
		fStatusLine.clear();
	}
	
	public static Icon getIconResource(Class clazz, String name) {
		URL url= clazz.getResource(name);
		if (url == null) {
			System.err.println("Warning: could not load \""+name+"\" icon");
			return null;
		} 
		return new ImageIcon(url);
	}
	
	private void about() {
		AboutDialog about= new AboutDialog(fFrame); 
		about.show();
	}
	

}