package org.eclipse.releng.generators;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.Enumeration;

import org.apache.tools.ant.Task;
import org.apache.xerces.parsers.DOMParser;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.eclipse.releng.Mailer;

/**
 * @version 	1.0
 * @author Dean Roberts
 */
public class TestResultsGenerator extends Task {

	static final String elementName = "testsuite";
	static final String testResultsToken = "%testresults%";
	static final String compileLogsToken = "%compilelogs%";
	private Vector dropTokens;
	private String testResultsWithProblems = "\n";

	private DOMParser parser = new DOMParser();
	private ErrorTracker anErrorTracker;
	private String testResultsTemplateString = "";
	private String dropTemplateString = "";
	private boolean testsRan = true;
	//assume tests ran.  If no html files are found, this is set to false

	//for backward compatability with old testManifest.xml
	private boolean useNewFormat = false;

	private Mailer mailer;

	// Parameters
	// build runs JUnit automated tests
	private boolean isBuildTested;

	// buildType used to determine if mail should be sent on
	// successful build completion
	private String buildType;

	// Comma separated list of drop tokens
	private String dropTokenList;

	// Location of the xml files
	private String xmlDirectoryName;

	// Location of the html files
	private String htmlDirectoryName;

	// Location of the resulting index.php file.
	private String dropDirectoryName;

	// Location and name of the template index.php file.
	private String testResultsTemplateFileName;

	// Location and name of the template drop index.php file.
	private String dropTemplateFileName;

	// Name of the generated index php file.
	private String testResultsHtmlFileName;

	// Name of the generated drop index php file;
	private String dropHtmlFileName;

	// Arbitrary path used in the index.php page to href the
	// generated .html files.
	private String hrefTestResultsTargetPath;

	// Aritrary path used in the index.php page to reference the compileLogs
	private String hrefCompileLogsTargetPath;

	// Location of compile logs base directory
	private String compileLogsDirectoryName;

	// Location and name of test manifest file
	private String testManifestFileName;

	public static void main(String[] args) {
		TestResultsGenerator test = new TestResultsGenerator();
		test.setUseNewFormat(true);
		test.setDropTokenList(
			"%sdk%,%tests%,%examples%,%runtime%,%jdt%,%teamextras%,%infocenter%");
		test.getDropTokensFromList(test.dropTokenList);
		test.setIsBuildTested(false);
		test.setXmlDirectoryName("D:\\junk\\testresults\\xml");
		test.setHtmlDirectoryName("D:\\junk\\testresults");
		test.setDropDirectoryName("D:\\junk");
		test.setTestResultsTemplateFileName(
			"D:\\junk\\templateFiles\\testResults.php.template");
		test.setDropTemplateFileName(
			"D:\\junk\\templateFiles\\index.php.template");
		test.setTestResultsHtmlFileName("testResults.php");
//		test.setDropHtmlFileName("index.php");
		test.setDropHtmlFileName("index.html");

		test.setHrefTestResultsTargetPath("testresults");
		test.setCompileLogsDirectoryName(
			"D:\\junk\\compilelogs");
		test.setHrefCompileLogsTargetPath("compilelogs");
		test.setTestManifestFileName("D:\\junk\\testManifest.xml");
		test.execute();
	}

	public void execute() {

		anErrorTracker = new ErrorTracker();
		anErrorTracker.loadFile(testManifestFileName);
		getDropTokensFromList(dropTokenList);
		testResultsTemplateString = readFile(testResultsTemplateFileName);
		dropTemplateString = readFile(dropTemplateFileName);
		System.out.println("Begin: Generating test results index page");
		System.out.println("Parsing XML files");
		parseXml();
		System.out.println("Parsing compile logs");
		parseCompileLogs();
		System.out.println("End: Generating test results indx page");
		writeTestResultsFile();
		writeDropIndexFile();
		mailResults();
	}

	public void parseCompileLogs() {

		String replaceString = "";
		replaceString =
			processCompileLogsDirectory(
				compileLogsDirectoryName,
				replaceString);
		if (replaceString == "") {
			replaceString = "None";
		}
		testResultsTemplateString =
			replace(testResultsTemplateString, compileLogsToken, replaceString);

	}

	private String processCompileLogsDirectory(
		String directoryName,
		String aString) {

		File sourceDirectory = new File(directoryName);
		String replaceString = aString;

		File[] directories = sourceDirectory.listFiles();
		Arrays.sort(directories);

		for (int i = 0; i < directories.length; i++) {
			if (directories[i].isDirectory()) {
				File[] logFiles = directories[i].listFiles();

				for (int j = 0; j < logFiles.length; j++) {
					String longName = logFiles[j].getPath();
					if (logFiles[j].isDirectory()) {
						replaceString =
							replaceString
								+ processCompileLogsDirectory(longName, aString);
					} else {
						if (longName.endsWith(".log")) {
							replaceString =
								replaceString + readCompileLog(longName);
						}
					}
				}
			} else
				replaceString =
					replaceString
						+ readCompileLog(directories[i].getAbsolutePath());

		}
		return replaceString;
	}

	private String readCompileLog(String log) {
		String fileContents = readFile(log);

		int errorCount = countCompileErrors(fileContents);
		int warningCount = countCompileWarnings(fileContents);
		if (errorCount != 0) {

			//use wildcard in place of version number on directory names
			String logName =
				log.substring(getCompileLogsDirectoryName().length() + 1);
			StringBuffer buffer = new StringBuffer(logName);
			buffer.replace(
				logName.indexOf("_") + 1,
				logName.indexOf(File.separator, logName.indexOf("_") + 1),
				"*");
			logName = new String(buffer);

			anErrorTracker.registerError(logName);
		}
		return formatCompileErrorRow(log, errorCount, warningCount);

	}

	private String readFile(String fileName) {

		try {
			FileInputStream aStream = new FileInputStream(fileName);
			byte[] aByteArray = new byte[aStream.available()];
			aStream.read(aByteArray);
			aStream.close();
			return new String(aByteArray);
		} catch (FileNotFoundException e) {
			System.out.println("File not found: " + fileName);
			return "";
		} catch (IOException e) {
			System.out.println("IOException: " + fileName);
			return "";
		}
	}

	private int countCompileErrors(String aString) {
		return extractNumber(aString, "error");
	}

	private int countCompileWarnings(String aString) {
		return extractNumber(aString, "warning");
	}

	private int extractNumber(String aString, String endToken) {
		int endIndex = aString.lastIndexOf(endToken);
		if (endIndex == -1) {
			return 0;
		}

		int startIndex = endIndex;
		while (startIndex >= 0
			&& aString.charAt(startIndex) != '('
			&& aString.charAt(startIndex) != ',') {
			startIndex--;
		};

		String count = aString.substring(startIndex + 1, endIndex).trim();
		try {
			return Integer.parseInt(count);
		} catch (NumberFormatException e) {
			return 0;
		}

	}

	private String verifyAllTestsRan(String directory) {
		Vector missingTestLogs = new Vector();
		Enumeration enumeration = (anErrorTracker.getTestLogs()).elements();

		String replaceString="";
		while (enumeration.hasMoreElements()) {
			String testLogName = enumeration.nextElement().toString();

			if (new File(directory + File.separator + testLogName)
				.exists()) 
				continue;

			anErrorTracker.registerError(testLogName);
			replaceString = replaceString + formatRow(testLogName, -1, false);
			testResultsWithProblems=testResultsWithProblems.concat("\n" + testLogName.substring(0,testLogName.length()-4) +" (file missing)");

			
		}
		return replaceString;
	}

	public void parseXml() {

		File sourceDirectory = new File(xmlDirectoryName);

		if (sourceDirectory.exists()) {

			String replaceString = "";

			File[] xmlFileNames = sourceDirectory.listFiles();
			Arrays.sort(xmlFileNames)	;	

			for (int i = 0; i < xmlFileNames.length; i++) {
				if (xmlFileNames[i].getPath().endsWith(".xml")) {
					String fullName = xmlFileNames[i].getPath();
					int errorCount = countErrors(fullName);
					if (errorCount != 0) {
						String testName =
							xmlFileNames[i].getName().substring(
								0,
								xmlFileNames[i].getName().length() - 4);
						testResultsWithProblems =
							testResultsWithProblems.concat("\n" + testName);
						anErrorTracker.registerError(
							fullName.substring(
								getXmlDirectoryName().length() + 1));
					}

					replaceString =
						replaceString
							+ formatRow(xmlFileNames[i].getPath(), errorCount,true);
				}
			}
			//check for missing test logs
			replaceString=replaceString+verifyAllTestsRan(xmlDirectoryName);
			
			testResultsTemplateString =
				replace(
					testResultsTemplateString,
					testResultsToken,
					replaceString);
			testsRan = true;

		} else {
			testsRan = false;
			System.out.println(
				"Test results not found in "
					+ sourceDirectory.getAbsolutePath());
		}

	}

	private String replace(
		String source,
		String original,
		String replacement) {

		int replaceIndex = source.indexOf(original);
		if (replaceIndex > -1) {
			String resultString = source.substring(0, replaceIndex);
			resultString = resultString + replacement;
			resultString =
				resultString
					+ source.substring(replaceIndex + original.length());
			return resultString;
		} else {
			System.out.println("Could not find token: " + original);
			return source;
		}

	}

	private void writeDropIndexFile() {

		String[] types = anErrorTracker.getTypes();
		for (int i = 0; i < types.length; i++) {
			PlatformStatus[] platforms = anErrorTracker.getPlatforms(types[i]);
			String replaceString = processDropRows(platforms);
			dropTemplateString =
				replace(
					dropTemplateString,
					dropTokens.get(i).toString(),
					replaceString);
		}

		String outputFileName =
			dropDirectoryName + File.separator + dropHtmlFileName;
		writeFile(outputFileName, dropTemplateString);

	}

	private String processDropRows(PlatformStatus[] platforms) {

		String result = "";
		for (int i = 0; i < platforms.length; i++) {
			result = result + processDropRow(platforms[i]);
		}

		return result;
	}

	private String processDropRow(PlatformStatus aPlatform) {

		String imageName = "";

		if (aPlatform.hasErrors()) {
			imageName =
				"<a href=\"testResults.php\"><img src = \"FAIL.gif\" width=19 height=23></a>";
		} else {
			if (testsRan) {
				imageName = "<img src = \"OK.gif\" width=19 height=23>";
			} else {
				if (isBuildTested) {
					imageName =
						"<font size=\"-1\" color=\"#FF0000\">pending</font>";
				} else {
					imageName = "<img src = \"OK.gif\" width=19 height=23>";
				}
			}
		}

		String result = "<tr>";

		result = result + "<td><div align=left>" + imageName + "</div></td>\n";
		result = result + "<td>" + aPlatform.getName() + "</td>";

		if (isUseNewFormat()){
			result = result + "<td><div align=\"center\">(<a href=\"download.php?dropFile="+aPlatform.getFileName() +"\">http</a>)\n";
			result = result + "&nbsp;&nbsp;<?php echo \"(<a href='ftp://$SERVER_NAME/@buildlabel@/"+aPlatform.getFileName() +"'>ftp</a>)</div></td>\" ?>\n";
		}

		result = result + "<td>" + aPlatform.getFileName() + " (<a href=\"checksum/"+aPlatform.getFileName()+".md5>md5</a>)</td>\n";
		result = result + "</tr>\n";

		return result;
	}

	private void writeTestResultsFile() {

		String outputFileName =
			dropDirectoryName + File.separator + testResultsHtmlFileName;
		writeFile(outputFileName, testResultsTemplateString);
	}

	private void writeFile(String outputFileName, String contents) {
		try {
			FileOutputStream outputStream =
				new FileOutputStream(outputFileName);
			outputStream.write(contents.getBytes());
			outputStream.close();
		} catch (FileNotFoundException e) {
			System.out.println(
				"File not found exception writing: " + outputFileName);
		} catch (IOException e) {
			System.out.println("IOException writing: " + outputFileName);
		}

	}

	public void setTestResultsHtmlFileName(String aString) {
		testResultsHtmlFileName = aString;
	}

	public String getTestResultsHtmlFileName() {
		return testResultsHtmlFileName;
	}

	public void setTestResultsTemplateFileName(String aString) {
		testResultsTemplateFileName = aString;
	}

	public String getTestResultsTemplateFileName() {
		return testResultsTemplateFileName;
	}

	public void setXmlDirectoryName(String aString) {
		xmlDirectoryName = aString;
	}

	public String getXmlDirectoryName() {
		return xmlDirectoryName;
	}

	public void setHtmlDirectoryName(String aString) {
		htmlDirectoryName = aString;
	}

	public String getHtmlDirectoryName() {
		return htmlDirectoryName;
	}

	public void setDropDirectoryName(String aString) {
		dropDirectoryName = aString;
	}

	public String getDropDirectoryName() {
		return dropDirectoryName;
	}

	private String formatCompileErrorRow(
		String fileName,
		int errorCount,
		int warningCount) {

		String aString = "";
		if (errorCount == 0 && warningCount == 0) {
			return aString;
		}

		int i = fileName.indexOf(getHrefCompileLogsTargetPath());

		String shortName =
			fileName.substring(i + getHrefCompileLogsTargetPath().length());

		aString = aString + "<tr><td>";

		aString =
			aString
				+ "<a href="
				+ "\""
				+ getHrefCompileLogsTargetPath()
				+ shortName
				+ "\">"
				+ shortName
				+ "</a>";

		// aString = aString + fileName;
		aString = aString + "</td><td>";
		aString = aString + errorCount;
		aString = aString + "</td><td>";
		aString = aString + warningCount;
		aString = aString + "</td></tr>";

		return aString;
	}

	private String formatRow(String fileName, int errorCount, boolean link) {

		// replace .xml with .html

		String aString = "";
		if (!link) {
			return "<tr><td>" + fileName + " (missing)" + "</td><td>" + "DNF";
		}

		if (fileName.endsWith(".xml")) {

			int begin = fileName.lastIndexOf(File.separatorChar);
			int end = fileName.lastIndexOf(".xml");

			String shortName = fileName.substring(begin + 1, end);

			aString = aString + "<tr><td>";
			aString =
				aString
					+ "<a href="
					+ "\""
					+ hrefTestResultsTargetPath
					+ "/"
					+ shortName
					+ ".html"
					+ "\">"
					+ shortName
					+ "</a>";

			aString = aString + "</td><td>";

			if (errorCount == -1)
				aString = aString + "DNF";

			else
				aString = aString + String.valueOf(errorCount);
			aString = aString + "</td></tr>";
		}

		return aString;

	}

	private int countErrors(String fileName) {

		try {
			parser.parse(fileName);

			Document document = parser.getDocument();
			NodeList elements = document.getElementsByTagName(elementName);

			int elementCount = elements.getLength();
			if (elementCount == 0)
				return -1;
			int errorCount = 0;
			for (int i = 0; i < elementCount; i++) {
				Element element = (Element) elements.item(i);
				NamedNodeMap attributes = element.getAttributes();
				Node aNode = attributes.getNamedItem("errors");
				errorCount =
					errorCount + Integer.parseInt(aNode.getNodeValue());
				aNode = attributes.getNamedItem("failures");
				errorCount =
					errorCount + Integer.parseInt(aNode.getNodeValue());

			}
			return errorCount;
		} catch (IOException e) {
			System.out.println("IOException: " + fileName);
			// e.printStackTrace();
			return 0;
		} catch (SAXException e) {
			System.out.println("SAXException: " + fileName);
			// e.printStackTrace();
			return 0;
		}
	}

	private void mailResults() {
		//send a different message for the following cases:
		//build is not tested at all
		//build is tested, tests have not run
		//build is tested, tests have run with error and or failures
		//build is tested, tests have run with no errors or failures
		try {
			mailer = new Mailer();
		} catch (NoClassDefFoundError e) {
			return;
		}
		String buildDownloadUrl = mailer.getBuildProperties().getDownloadUrl()+"/"+mailer.getBuildProperties().getBuildLabel();
		String subject = "Build is complete.  ";
		String message = "The build is complete.  \n\n"+buildDownloadUrl;

		if (testsRan) {
			subject = "Automated JUnit Testing complete.  ";
			message = "Automated JUnit testing is complete.  ";
			subject =
				subject.concat(
					(testResultsWithProblems.endsWith("\n"))
						? "All tests pass"
						: "Test failures/errors occurred.");
			message =
				message.concat(
					(testResultsWithProblems.endsWith("\n"))
						? "All tests pass"
						: "Test failures/errors occurred in the following:  "
							+ testResultsWithProblems)+"\n\n"+buildDownloadUrl+"/"+testResultsHtmlFileName;
		} else if (isBuildTested && (!buildType.equals("N"))) {
			subject = subject.concat("Automated JUnit testing is starting.");
			message = "The " + subject+"\n\n"+buildDownloadUrl;
		}

		if (subject.endsWith("Test failures/errors occurred."))
			mailer.sendMessage(subject, message);
		else if (!buildType.equals("N"))
			mailer.sendMessage(subject, message);

	}

	/**
	 * Gets the hrefTestResultsTargetPath.
	 * @return Returns a String
	 */
	public String getHrefTestResultsTargetPath() {
		return hrefTestResultsTargetPath;
	}

	/**
	 * Sets the hrefTestResultsTargetPath.
	 * @param hrefTestResultsTargetPath The hrefTestResultsTargetPath to set
	 */
	public void setHrefTestResultsTargetPath(String htmlTargetPath) {
		this.hrefTestResultsTargetPath = htmlTargetPath;
	}

	/**
	 * Gets the compileLogsDirectoryName.
	 * @return Returns a String
	 */
	public String getCompileLogsDirectoryName() {
		return compileLogsDirectoryName;
	}

	/**
	 * Sets the compileLogsDirectoryName.
	 * @param compileLogsDirectoryName The compileLogsDirectoryName to set
	 */
	public void setCompileLogsDirectoryName(String compileLogsDirectoryName) {
		this.compileLogsDirectoryName = compileLogsDirectoryName;
	}

	/**
	 * Gets the hrefCompileLogsTargetPath.
	 * @return Returns a String
	 */
	public String getHrefCompileLogsTargetPath() {
		return hrefCompileLogsTargetPath;
	}

	/**
	 * Sets the hrefCompileLogsTargetPath.
	 * @param hrefCompileLogsTargetPath The hrefCompileLogsTargetPath to set
	 */
	public void setHrefCompileLogsTargetPath(String hrefCompileLogsTargetPath) {
		this.hrefCompileLogsTargetPath = hrefCompileLogsTargetPath;
	}

	/**
	 * Gets the testManifestFileName.
	 * @return Returns a String
	 */
	public String getTestManifestFileName() {
		return testManifestFileName;
	}

	/**
	 * Sets the testManifestFileName.
	 * @param testManifestFileName The testManifestFileName to set
	 */
	public void setTestManifestFileName(String testManifestFileName) {
		this.testManifestFileName = testManifestFileName;
	}

	/**
	 * Gets the dropHtmlFileName.
	 * @return Returns a String
	 */
	public String getDropHtmlFileName() {
		return dropHtmlFileName;
	}

	/**
	 * Sets the dropHtmlFileName.
	 * @param dropHtmlFileName The dropHtmlFileName to set
	 */
	public void setDropHtmlFileName(String dropHtmlFileName) {
		this.dropHtmlFileName = dropHtmlFileName;
	}

	/**
	 * Gets the dropTemplateFileName.
	 * @return Returns a String
	 */
	public String getDropTemplateFileName() {
		return dropTemplateFileName;
	}

	/**
	 * Sets the dropTemplateFileName.
	 * @param dropTemplateFileName The dropTemplateFileName to set
	 */
	public void setDropTemplateFileName(String dropTemplateFileName) {
		this.dropTemplateFileName = dropTemplateFileName;
	}

	private void getDropTokensFromList(String list) {
		int i = 0;
		StringTokenizer tokenizer = new StringTokenizer(list, ",");
		dropTokens = new Vector();

		while (tokenizer.hasMoreTokens()) {
			dropTokens.add(tokenizer.nextToken());
		}
	}

	public String getDropTokenList() {
		return dropTokenList;
	}

	public void setDropTokenList(String dropTokenList) {
		this.dropTokenList = dropTokenList;
	}

	public boolean isBuildTested() {
		return isBuildTested;
	}

	public void setIsBuildTested(boolean isBuildTested) {
		this.isBuildTested = isBuildTested;
	}

	/**
	 * Returns the buildType.
	 * @return String
	 */
	public String getBuildType() {
		return buildType;
	}

	/**
	 * Sets the buildType.
	 * @param buildType The buildType to set
	 */
	public void setBuildType(String buildType) {
		this.buildType = buildType;
	}

	/**
	 * @return boolean
	 */
	public boolean isUseNewFormat() {
		return useNewFormat;
}
	/**
	 * Sets the useNewFormat.
	 * @param useNewFormat The useNewFormat to set
	 */
	public void setUseNewFormat(boolean useNewFormat) {
		this.useNewFormat = useNewFormat;
	}

}