package junit.awtui;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.ImageProducer;
import java.util.Vector;

import junit.framework.*;
import junit.runner.*;

/**
 * An AWT 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.awtui.TestRunner [-noloading] [TestCase]
 * </pre>
 * TestRunner takes as an optional argument the name of the testcase class to be run.
 */
 public class TestRunner extends BaseTestRunner {
	protected Frame fFrame;
	protected Vector fExceptions;
	protected Vector fFailedTests;
	protected Thread fRunner;
	protected TestResult fTestResult;

	protected TextArea fTraceArea;
	protected TextField fSuiteField;
	protected Button fRun;
	protected ProgressBar fProgressIndicator;
	protected List fFailureList;
	protected Logo fLogo;
	protected Label fNumberOfErrors;
	protected Label fNumberOfFailures;
	protected Label fNumberOfRuns;
	protected Button fQuitButton;
	protected Button fRerunButton;
	protected TextField fStatusLine;
	protected Checkbox fUseLoadingRunner;

	protected static final Font PLAIN_FONT= new Font("dialog", Font.PLAIN, 12);
	private static final int GAP= 4;

	public TestRunner() {
	}

	private void about() {
		AboutDialog about= new AboutDialog(fFrame);
		about.setModal(true);
		about.setLocation(300, 300);
		about.setVisible(true);
	}

	public void testStarted(String testName) {
		showInfo("Running: "+testName);
	}

	public void testEnded(String testName) {
		setLabelValue(fNumberOfRuns, fTestResult.runCount());
		synchronized(this) {
			fProgressIndicator.step(fTestResult.wasSuccessful());
		}
	}

	public void testFailed(int status, Test test, Throwable t) {
		switch (status) {
			case TestRunListener.STATUS_ERROR:
				fNumberOfErrors.setText(Integer.toString(fTestResult.errorCount()));
				appendFailure("Error", test, t);
				break;
			case TestRunListener.STATUS_FAILURE:
				fNumberOfFailures.setText(Integer.toString(fTestResult.failureCount()));
				appendFailure("Failure", test, t);
				break;
		}
	}

	protected void addGrid(Panel 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);
	}

	private void appendFailure(String kind, Test test, Throwable t) {
		kind+= ": " + test;
		String msg= t.getMessage();
		if (msg != null) {
			kind+= ":" + truncate(msg);
		}
		fFailureList.add(kind);
		fExceptions.addElement(t);
		fFailedTests.addElement(test);
		if (fFailureList.getItemCount() == 1) {
			fFailureList.select(0);
			failureSelected();
		}
	}
	/**
	 * Creates the JUnit menu. Clients override this
	 * method to add additional menu items.
	 */
	protected Menu createJUnitMenu() {
		Menu menu= new Menu("JUnit");
		MenuItem mi= new MenuItem("About...");
		mi.addActionListener(
		    new ActionListener() {
		        public void actionPerformed(ActionEvent event) {
		            about();
		        }
		    }
		);
		menu.add(mi);

		menu.addSeparator();
		mi= new MenuItem("Exit");
		mi.addActionListener(
		    new ActionListener() {
		        public void actionPerformed(ActionEvent event) {
		            System.exit(0);
		        }
		    }
		);
		menu.add(mi);
		return menu;
	}

	protected void createMenus(MenuBar mb) {
		mb.add(createJUnitMenu());
	}
	protected TestResult createTestResult() {
		return new TestResult();
	}

	protected Frame createUI(String suiteName) {
		Frame frame= new Frame("JUnit");
		Image icon= loadFrameIcon();
		if (icon != null)
			frame.setIconImage(icon);

		frame.setLayout(new BorderLayout(0, 0));
		frame.setBackground(SystemColor.control);
		final Frame finalFrame= frame;

		frame.addWindowListener(
			new WindowAdapter() {
				public void windowClosing(WindowEvent e) {
					finalFrame.dispose();
					System.exit(0);
				}
			}
		);

		MenuBar mb = new MenuBar();
		createMenus(mb);
		frame.setMenuBar(mb);

		//---- first section
		Label suiteLabel= new Label("Test class name:");

		fSuiteField= new TextField(suiteName != null ? suiteName : "");
		fSuiteField.selectAll();
		fSuiteField.requestFocus();
		fSuiteField.setFont(PLAIN_FONT);
		fSuiteField.setColumns(40);
		fSuiteField.addActionListener(
			new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					runSuite();
				}
			}
		);
		fSuiteField.addTextListener(
			new TextListener() {
				public void textValueChanged(TextEvent e) {
					fRun.setEnabled(fSuiteField.getText().length() > 0);
					fStatusLine.setText("");
				}
			}
		);
		fRun= new Button("Run");
		fRun.setEnabled(false);
		fRun.addActionListener(
			new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					runSuite();
				}
			}
		);
		boolean useLoader= useReloadingTestSuiteLoader();
		fUseLoadingRunner= new Checkbox("Reload classes every run", useLoader);
		if (inVAJava())
			fUseLoadingRunner.setVisible(false);

		//---- second section
		fProgressIndicator= new ProgressBar();

		//---- third section
		fNumberOfErrors= new Label("0000", Label.RIGHT);
		fNumberOfErrors.setText("0");
		fNumberOfErrors.setFont(PLAIN_FONT);

		fNumberOfFailures= new Label("0000", Label.RIGHT);
		fNumberOfFailures.setText("0");
		fNumberOfFailures.setFont(PLAIN_FONT);

		fNumberOfRuns= new Label("0000", Label.RIGHT);
		fNumberOfRuns.setText("0");
		fNumberOfRuns.setFont(PLAIN_FONT);

		Panel numbersPanel= createCounterPanel();

		//---- fourth section
		Label failureLabel= new Label("Errors and Failures:");

		fFailureList= new List(5);
		fFailureList.addItemListener(
			new ItemListener() {
				public void itemStateChanged(ItemEvent e) {
					failureSelected();
				}
			}
		);
		fRerunButton= new Button("Run");
		fRerunButton.setEnabled(false);
		fRerunButton.addActionListener(
			new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					rerun();
				}
			}
		);

		Panel failedPanel= new Panel(new GridLayout(0, 1, 0, 2));
		failedPanel.add(fRerunButton);

		fTraceArea= new TextArea();
		fTraceArea.setRows(5);
		fTraceArea.setColumns(60);

		//---- fifth section
		fStatusLine= new TextField();
		fStatusLine.setFont(PLAIN_FONT);
		fStatusLine.setEditable(false);
		fStatusLine.setForeground(Color.red);

		fQuitButton= new Button("Exit");
		fQuitButton.addActionListener(
			new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					System.exit(0);
				}
			}
		);

		// ---------
		fLogo= new Logo();

		//---- overall layout
		Panel panel= new Panel(new GridBagLayout());

		addGrid(panel, suiteLabel,		 0, 0, 2, GridBagConstraints.HORIZONTAL, 	1.0, GridBagConstraints.WEST);

		addGrid(panel, fSuiteField, 	 0, 1, 2, GridBagConstraints.HORIZONTAL, 	1.0, GridBagConstraints.WEST);
		addGrid(panel, fRun, 			 2, 1, 1, GridBagConstraints.HORIZONTAL, 	0.0, GridBagConstraints.CENTER);
		addGrid(panel, fUseLoadingRunner, 0, 2, 2, GridBagConstraints.NONE, 	1.0, GridBagConstraints.WEST);
		addGrid(panel, fProgressIndicator, 0, 3, 2, GridBagConstraints.HORIZONTAL, 	1.0, GridBagConstraints.WEST);
		addGrid(panel, fLogo, 			 2, 3, 1, GridBagConstraints.NONE, 			0.0, GridBagConstraints.NORTH);

		addGrid(panel, numbersPanel,	 0, 4, 2, GridBagConstraints.NONE, 			0.0, GridBagConstraints.WEST);

		addGrid(panel, failureLabel, 	 0, 5, 2, GridBagConstraints.HORIZONTAL, 	1.0, GridBagConstraints.WEST);
		addGrid(panel, fFailureList, 	 0, 6, 2, GridBagConstraints.BOTH, 			1.0, GridBagConstraints.WEST);
		addGrid(panel, failedPanel, 	 2, 6, 1, GridBagConstraints.HORIZONTAL, 	0.0, GridBagConstraints.CENTER);
		addGrid(panel, fTraceArea, 	     0, 7, 2, GridBagConstraints.BOTH, 			1.0, GridBagConstraints.WEST);

		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.add(panel, BorderLayout.CENTER);
		frame.pack();
		return frame;
	}

	protected Panel createCounterPanel() {
		Panel numbersPanel= new Panel(new GridBagLayout());
		addToCounterPanel(
			numbersPanel,
			new Label("Runs:"),
			0, 0, 1, 1, 0.0, 0.0,
          	GridBagConstraints.CENTER, GridBagConstraints.NONE,
          	new Insets(0, 0, 0, 0) 
		);	
		addToCounterPanel(
			numbersPanel,
			fNumberOfRuns, 
          	1, 0, 1, 1, 0.33, 0.0,
          	GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
          	new Insets(0, 8, 0, 40)
		);
		addToCounterPanel(
			numbersPanel,
			new Label("Errors:"),
          	2, 0, 1, 1, 0.0, 0.0,
          	GridBagConstraints.CENTER, GridBagConstraints.NONE,
          	new Insets(0, 8, 0, 0)
		);
		addToCounterPanel(
			numbersPanel,
			fNumberOfErrors,
          	3, 0, 1, 1, 0.33, 0.0,
          	GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
          	new Insets(0, 8, 0, 40)
		);
		addToCounterPanel(
			numbersPanel,
			new Label("Failures:"),
          	4, 0, 1, 1, 0.0, 0.0,
          	GridBagConstraints.CENTER, GridBagConstraints.NONE,
          	new Insets(0, 8, 0, 0)
		);	
		addToCounterPanel(
			numbersPanel,
			fNumberOfFailures,
          	5, 0, 1, 1, 0.33, 0.0,
          	GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
          	new Insets(0, 8, 0, 0) 
		);
		return numbersPanel;
	}

	private void addToCounterPanel(Panel counter, Component comp,
	    	int gridx, int gridy, int gridwidth, int gridheight,
			double weightx, double weighty,
			int anchor, int fill,
			Insets insets) {
		
		GridBagConstraints constraints= new GridBagConstraints();
		constraints.gridx= gridx;
		constraints.gridy= gridy;
		constraints.gridwidth= gridwidth;
		constraints.gridheight= gridheight;
		constraints.weightx= weightx;
		constraints.weighty= weighty;
		constraints.anchor= anchor;
		constraints.fill= fill;
		constraints.insets= insets;
		counter.add(comp, constraints);
	}


	public void failureSelected() {
		fRerunButton.setEnabled(isErrorSelected());
		showErrorTrace();
	}

	private boolean isErrorSelected() {
		return fFailureList.getSelectedIndex() != -1;
	}

	private Image loadFrameIcon() {
		Toolkit toolkit= Toolkit.getDefaultToolkit();
		try {
			java.net.URL url= BaseTestRunner.class.getResource("smalllogo.gif");
			return toolkit.createImage((ImageProducer) url.getContent());
		} catch (Exception ex) {
		}
		return null;
	}

	public Thread getRunner() {
		return fRunner;
	}

	public static void main(String[] args) {
		new TestRunner().start(args);
	}

	public static void run(Class test) {
		String args[]= { test.getName() };
		main(args);
	}

	public void rerun() {
		int index= fFailureList.getSelectedIndex();
		if (index == -1)
			return;

		Test test= (Test)fFailedTests.elementAt(index);
		rerunTest(test);
	}

	private void rerunTest(Test test) {
		if (!(test instanceof TestCase)) {
			showInfo("Could not reload "+ test.toString());
			return;
		}
		Test reloadedTest= null;
		TestCase rerunTest= (TestCase)test;
		try {
			Class reloadedTestClass= getLoader().reload(test.getClass()); 
			reloadedTest= TestSuite.createTest(reloadedTestClass, rerunTest.getName());
		} 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() {
		setLabelValue(fNumberOfErrors, 0);
		setLabelValue(fNumberOfFailures, 0);
		setLabelValue(fNumberOfRuns, 0);
		fProgressIndicator.reset();
		fRerunButton.setEnabled(false);
		fFailureList.removeAll();
		fExceptions= new Vector(10);
		fFailedTests= new Vector(10);
		fTraceArea.setText("");

	}

	protected void runFailed(String message) {
		showStatus(message);
		fRun.setLabel("Run");
		fRunner= null;
	}

	synchronized public void runSuite() {
		if (fRunner != null && fTestResult != null) {
			fTestResult.stop();
		} else {
			setLoading(shouldReload());
			fRun.setLabel("Stop");
			showInfo("Initializing...");
			reset();

			showInfo("Load Test Case...");

			final Test testSuite= getTest(fSuiteField.getText());
			if (testSuite != null) {
				fRunner= new Thread() {
					public void run() {
						fTestResult= createTestResult();
						fTestResult.addListener(TestRunner.this);
						fProgressIndicator.start(testSuite.countTestCases());
						showInfo("Running...");

						long startTime= System.currentTimeMillis();
						testSuite.run(fTestResult);

						if (fTestResult.shouldStop()) {
							showStatus("Stopped");
						} else {
							long endTime= System.currentTimeMillis();
							long runTime= endTime-startTime;
							showInfo("Finished: " + elapsedTimeAsString(runTime) + " seconds");
						}
						fTestResult= null;
						fRun.setLabel("Run");
						fRunner= null;
						System.gc();
					}
				};
				fRunner.start();
			}
		}
	}

	private boolean shouldReload() {
		return !inVAJava() && fUseLoadingRunner.getState();
	}

	private void setLabelValue(Label label, int value) {
		label.setText(Integer.toString(value));
		label.invalidate();
		label.getParent().validate();

	}

	public void setSuiteName(String suite) {
		fSuiteField.setText(suite);
	}

	private void showErrorTrace() {
		int index= fFailureList.getSelectedIndex();
		if (index == -1)
			return;

		Throwable t= (Throwable) fExceptions.elementAt(index);
		fTraceArea.setText(getFilteredTrace(t));
	}


	private void showInfo(String message) {
		fStatusLine.setFont(PLAIN_FONT);
		fStatusLine.setForeground(Color.black);
		fStatusLine.setText(message);
	}

	protected void clearStatus() {
		showStatus("");
	}

	private void showStatus(String status) {
		fStatusLine.setFont(PLAIN_FONT);
		fStatusLine.setForeground(Color.red);
		fStatusLine.setText(status);
	}
	/**
	 * Starts the TestRunner
	 */
	public void start(String[] args) {
		String suiteName= processArguments(args);
		fFrame= createUI(suiteName);
		fFrame.setLocation(200, 200);
		fFrame.setVisible(true);

		if (suiteName != null) {
			setSuiteName(suiteName);
			runSuite();
		}
	}
}