package org.eclipse.europa.tools.webgen;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class WebPageGenerator {
	public LogFileParser parser;

	public File directory;

	public String generated_date;

	public String build_date;

	public Map<String, Map<String, Object>> featureSiteResults;

	public WebPageGenerator(LogFileParser p, File dir, String bd, String sd,
			Map<String, Map<String, Object>> results) {
		this.parser = p;
		this.directory = dir;
		this.build_date = bd;
		this.generated_date = sd;
		this.featureSiteResults = results;
	}

	public void generate() throws IOException {
		generate_full_log_page();
		for (Iterator<ProjectLog> iterator = this.parser.projects.iterator(); iterator
				.hasNext();) {
			ProjectLog project = iterator.next();
			generate_project_log_page(project);
			if (project.project.equals("update site.xml")
					&& featureSiteResults.get("") != null
					&& !featureSiteResults.get("").isEmpty())
				add_extra_features_feature(project);
			for (Iterator<FeatureLog> iter2 = project.features.iterator(); iter2
					.hasNext();) {
				FeatureLog feature = iter2.next();
				Map<String, Object> projmap = featureSiteResults
						.get(project.project);
				Object missing = null;
				if (projmap != null)
					missing = projmap.get(feature.feature);
				generate_feature_log_page(feature, missing);
			}
		}
		parser.scan_for_status();
		generate_index_page();
	}

	void add_extra_features_feature(ProjectLog project) {
		FeatureLog feature = new FeatureLog(project, "extra features", "");
		feature.lines = new ArrayList<LogLine>();
		feature.lines
				.add(new LogLine(
						"Feature Missing: Extra features in site.xml AND not in feature-{project}.xml files.",
						feature.lines.size() + 1));
		for (Iterator iterator = featureSiteResults.get("").keySet().iterator(); iterator
				.hasNext();) {
			String id = (String) iterator.next();
			feature.lines.add(new LogLine(
					"Feature Missing: &nbsp;&nbsp;&nbsp;&nbsp;" + id,
					feature.lines.size() + 1));
		}
		project.features.add(feature);
	}

	public void generate_full_log_page() throws IOException {
		generate_log_page(full_log_file(), "Complete Build Log",
				this.parser.lines);
		for (Iterator<LogLine> iterator = this.parser.lines.iterator(); iterator
				.hasNext();) {
			LogLine line = iterator.next();
			line.saveAnchor();
		}
	}

	public void generate_project_log_page(ProjectLog project)
			throws IOException {
		generate_log_page(project_log_file(project), project.project
				+ " Build Log", project.lines);
	}

	public void generate_feature_log_page(FeatureLog feature, Object missing)
			throws IOException {
		List<LogLine> lines = new ArrayList<LogLine>();
		for (Iterator iterator = feature.lines.iterator(); iterator.hasNext();) {
			LogLine line = (LogLine) iterator.next();
			lines.add(line);
		}
		if (missing != null) {
			lines
					.add(new LogLine(
							"Feature Missing: This feature is missing from the org.eclipse.europa.updatesite/WebContents/site.xml file",
							lines.size() + 1));
			lines
					.add(new LogLine(
							"Feature Missing: Please enter this feature in the site.xml so that it can be classified",
							lines.size() + 1));
			lines
					.add(new LogLine(
							"Feature Missing: &nbsp;&nbsp;&nbsp;&nbsp;under the correct category. When entering the feature and category in",
							lines.size() + 1));
			lines
					.add(new LogLine(
							"Feature Missing: &nbsp;&nbsp;&nbsp;&nbsp;the site.xml file, there is no need to worry about the version - it",
							lines.size() + 1));
			lines
					.add(new LogLine(
							"Feature Missing: &nbsp;&nbsp;&nbsp;&nbsp;will be updated automatically by the build system from the information",
							lines.size() + 1));
			lines
					.add(new LogLine(
							"Feature Missing: &nbsp;&nbsp;&nbsp;&nbsp;in the feature-{project}.xml file.",
							lines.size() + 1));
			feature.lines = lines;
		}
		feature.scan_for_status();
		generate_log_page(feature_log_file(feature), feature.feature
				+ " Build Log", feature.lines);
	}

	public static String success_color() {
		return "#CCFFCC";
	}

	public static String fail_color() {
		return "#FFCCCC";
	}

	public static String information_color() {
		return "#F4E0FF";
	}

	private File index_file() throws IOException {
		return new File(this.directory, "index.html");
	}

	private File full_log_file() throws IOException {
		return new File(this.directory, "fulllog.html");
	}

	private File project_log_file(ProjectLog project) throws IOException {
		return new File(this.directory, project.project + "-log.html");
	}

	private File feature_log_file(FeatureLog feature) throws IOException {
		return new File(this.directory, feature.project.project + "-"
				+ feature.feature + "-log.html");
	}

	private String project_url(ProjectLog project) throws IOException {
		return "#" + project.project;
	}

	public String status_style(Status status) {
		if (status.isFail()) {
			return " style=\"background-color: " + fail_color() + ";\"";
		}
		if (status.isSuccess()) {
			return " style=\"background-color: " + success_color() + ";\"";
		}
		return "";
	}

	public void write_header(PrintWriter writer, String title)
			throws IOException {
		writer.println("<html>");
		writer.println("<head>");
		writer.println("<title>" + title + "</title>");
		writer
				.println("<link rel=\"stylesheet\" type=\"text/css\" href=\"http://www.eclipse.org/eclipse.org-common/themes/Phoenix/css/visual.css\" media=\"screen\" />");
		writer.println("</head><body>");
		writer
				.println("<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">");
		writer
				.println("<tr style=\"background-image: url(http://dash.eclipse.org/dash/commits/web-app/header_bg.gif);\">");
		writer.println("<td>");
		writer
				.println("<a href=\"http://www.eclipse.org/\"><img src=\"http://dash.eclipse.org/dash/commits/web-app/header_logo.gif\" width=\"163\" height=\"68\" border=\"0\" alt=\"Eclipse Logo\" class=\"logo\" /></a>");
		writer.println("</td>");
		writer
				.println("<td align=\"right\" style=\"color: white; font-family: verdana,arial,helvetica; font-size: 1.25em; font-style: italic;\"><b>"
						+ title + "&nbsp;</b></font> </td>");
		writer.println("</tr>");
		writer.println("</table>");
		writer.println("<p><em><font size=-1>Build started " + this.build_date
				+ "; completed " + this.generated_date + "</font></em></p>");
	}

	public void write_footer(PrintWriter writer) throws IOException {
		writer.println("<p><em><font size=-1>Build started " + this.build_date
				+ "; completed " + this.generated_date + "</font></em></p>");
		writer.println("</body>");
		writer.println("</html>");
	}

	public void generate_index_page() throws IOException {
		File f = index_file();
		if (!f.exists())
			f.createNewFile();
		PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(
				f)));
		write_header(writer, "Europa Build Status");

		generate_main_table(writer);
		for (Iterator<ProjectLog> iterator = this.parser.projects.iterator(); iterator
				.hasNext();) {
			ProjectLog project = iterator.next();
			generate_project_table(project, writer);
		}
		write_footer(writer);
		writer.close();
	}

	public void generate_main_table(PrintWriter writer) throws IOException {
		writer.println("<h1" + status_style(this.parser.status)
				+ ">Overall Status: " + this.parser.status + "</h1>");
		writer
				.println("<table align=center border=1><tr><th colspan=2>Projects</th></tr>");
		for (Iterator<ProjectLog> iterator = this.parser.projects.iterator(); iterator
				.hasNext();) {
			ProjectLog project = iterator.next();
			writer.println("<tr " + status_style(project.status)
					+ "><td><a href=\"" + project_url(project) + "\">"
					+ project.project + "</a></td><td><a href=\""
					+ full_log_file().getName()
					+ anchor_if_any(project.lines, 2) + "\">" + project.status
					+ "</a></td></tr>");
		}
		writer.println("<tr><td align=center colspan=2><a href=\""
				+ full_log_file().getName()
				+ "\">Complete build log</a></td></tr>");
		writer
				.println("<tr><td align=center colspan=2><a href=\"http://download.eclipse.org/releases/europa/staging/site.xml\">Staging update site</a></td></tr>");
		writer
				.println("<tr><td align=center colspan=2><a href=\"http://wiki.eclipse.org/index.php/Europa_Simultaneous_Release#Europa_Builds\">Europa wiki page</a></td></tr>");
		writer
				.println("<tr><td align=center colspan=2><a href=\"http://www.eclipse.org/epp/download.php\">Packaging Project Downloads</a></td></tr>");
		writer.println("</table>");
	}

	public void generate_project_table(ProjectLog project, PrintWriter writer)
			throws IOException {
		writer.println("<a name=\"" + project.project + "\"><h2"
				+ status_style(project.status) + ">" + project.project
				+ " Status: " + project.status + "</h2></a>");

		writer
				.println("<table align=center border=1><tr><th colspan=2>Features</th></tr>");
		for (Iterator<FeatureLog> iterator = project.features.iterator(); iterator
				.hasNext();) {
			FeatureLog feature = iterator.next();
			writer.println("<tr " + status_style(feature.status)
					+ "><td><a href=\"" + feature_log_file(feature).getName()
					+ "\">" + feature.feature + " " + feature.version
					+ "</a></td><td><a href=\""
					+ feature_log_file(feature).getName()
					+ anchor_if_any(feature.lines, 1) + "\">" + feature.status
					+ "</a></td></tr>");
		}
		writer.println("<tr><td align=center colspan=2><a href=\""
				+ project_log_file(project).getName() + "\">" + project.project
				+ " build log</a></td></tr>");
		writer.println("</table>");
	}

	public void generate_log_page(File f, String header, List<LogLine> lines)
			throws IOException {
		if (!f.exists())
			f.createNewFile();
		List<LogLine> anchors = new ArrayList<LogLine>();
		for (Iterator<LogLine> iterator = lines.iterator(); iterator.hasNext();) {
			LogLine line = iterator.next();
			if (line.status.isFail()) {
				line.addAnchor();
				anchors.add(line);
			}
		}
		PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(
				f)));
		write_header(writer, "Europa Build Log");
		writer.println("<h1>" + header + "</h1>");
		if (!anchors.isEmpty()) {
			writer.println("<p>Errors: ");
			for (Iterator<LogLine> iterator = anchors.iterator(); iterator
					.hasNext();) {
				LogLine line = iterator.next();
				writer.println("<a href=\"#" + line.anchor
						+ "\"><span style=\"background-color: " + fail_color()
						+ "\">" + line.linenumber + "</span></a> ");
			}
			writer.println("</p>");
		}
		for (Iterator<LogLine> iterator = lines.iterator(); iterator.hasNext();) {
			LogLine line = iterator.next();
			line.write_log_line(writer);
			writer.println("<br>");
		}
		write_footer(writer);
		writer.close();
	}

	public String anchor_if_any(List<LogLine> lines, int anchor_number) {
		for (Iterator<LogLine> iterator = lines.iterator(); iterator.hasNext();) {
			LogLine line = iterator.next();
			String anchor = anchor_number == 1 ? line.anchor : line.anchor2;
			if (line.status.isFail() && anchor != null)
				return "#" + anchor;
		}
		return "";
	}
}
