package org.eclipse.europa.tools.webgen;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.europa.tools.webgen.Status.Pack200Type;

public class FeatureLog {
	public ProjectLog project;

	public String feature;

	public String version;

	public Status status;

	public List<LogLine> lines;

	public int packed = 0;

	public int skipped = 0;
	
	public FeatureLog(ProjectLog p, String f, String v) {
		this.project = p;
		this.feature = f;
		this.version = v;
		lines = new ArrayList<LogLine>();
	}

	public void scan_for_status() {
		this.status = Status.unknown;
		setStatusBasedOnPack200();
		Pattern[] ps = new Pattern[2];
		Status[] ss = new Status[ps.length];
		for (int i = 0; i < ss.length; i++) {
			ss[i] = Status.success;
		}
		ps[0] = Pattern.compile("\\] Command completed successfully");
		ps[1] = Pattern.compile("BUILD SUCCESSFUL");

		Pattern[] pe = new Pattern[16];
		Status[] se = new Status[pe.length];
		for (int i = 0; i < se.length; i++) {
			se[i] = Status.fail;
		}
		pe[0] = Pattern.compile("\\] !MESSAGE Application error");
		pe[1] = Pattern
				.compile("\\] org.eclipse.core.runtime.AssertionFailedException: assertion failed: Plug-in version identifier, \\\"[^\"]+\\\", can contain a maximum of four components.");
		se[1] = Status.fail_bad_version_number;
		pe[2] = Pattern
				.compile("\\] !MESSAGE An exception occured while downloading feature from");
		pe[3] = Pattern.compile("\\] java.io.FileNotFoundException: ");
		se[3] = Status.fail_file_not_found;
		pe[4] = Pattern
				.compile("\\] Command failed. Please check log file");
		pe[5] = Pattern
				.compile("\\] !MESSAGE No matching features found");
		se[5] = Status.no_matching_features;
		pe[6] = Pattern
				.compile("\\] !MESSAGE Unable to retrieve remote reference \\\".*\\\". \\[Server returned HTTP response code: \\\"404 Not Found\\\" for URL: ");
		se[6] = Status.fail_file_not_found;
		pe[7] = Pattern.compile("SIGSEGV");
		se[7] = Status.internal_error;
		pe[8] = Pattern.compile("java.lang.OutOfMemoryError");
		se[8] = Status.internal_error;
		pe[9] = Pattern
				.compile("java.lang.IllegalArgumentException: invalid qualifier");
		se[9] = Status.fail_bad_version_number;
		pe[10] = Pattern.compile("No such file or directory");
		se[10] = Status.fail_file_not_found;
		pe[11] = Pattern.compile("Feature Missing:");
		se[11] = Status.feature_not_in_site_xml;
		pe[12] = Pattern.compile("The following ID was not found, so was skipped, and is not on miror site");
		se[12] = Status.fail_file_not_found;
		pe[13] = Pattern.compile("License Error");
		se[13] = Status.license_error;
		pe[14] = Pattern.compile("Error zero length file");
		se[14] = Status.packing_corruption;
		pe[15] = Pattern.compile("org.xml.sax.SAXParseException");
		se[15] = Status.fail;

		for (Iterator<LogLine> iterator = lines.iterator(); iterator.hasNext();) {
			LogLine line = iterator.next();
			for (int i = 0; i < ps.length; i++) {
				Pattern pattern = ps[i];
				Matcher ms = pattern.matcher(line.line);
				if (ms.find())
					line.status = ss[i];
			}
			for (int i = 0; i < pe.length; i++) {
				Pattern pattern = pe[i];
				Matcher me = pattern.matcher(line.line);
				if (me.find())
					line.status = se[i];
			}
			this.status = this.status.combine(line.status);
		}
	}

	public void setStatusBasedOnPack200() {
		if (this.packed > 0 && this.skipped == 0)
			this.status = this.status.addPack200Status(Pack200Type.All);
		else if (this.packed == 0 && this.skipped > 0)
			this.status = this.status.addPack200Status(Pack200Type.None);
		else if (this.packed > 0 && this.skipped > 0)
			this.status = this.status.addPack200Status(Pack200Type.Some);
	}
//
//	public void scanForPack200Status(List<ProjectLog> projects) {
//		Pattern pRunningFeature = Pattern
//				.compile("Running Pack on .*/features/([a-z][a-z0-9\\._]+)_");
//		Pattern pSkippingFeature = Pattern
//				.compile("Skipping .*/features/([a-z][a-z0-9\\._]+)_");
//		for (Iterator<LogLine> iterator = lines.iterator(); iterator.hasNext();) {
//			LogLine line = iterator.next();
//			Matcher mRunningFeature = pRunningFeature.matcher(line.line);
//			if (mRunningFeature.find()) {
//				FeatureLog feature = findFeatureForFeature(mRunningFeature
//						.group(1), projects);
//				if( feature != null) feature.packed++;
//			}
//			Matcher mSkippingFeature = pSkippingFeature.matcher(line.line);
//			if (mSkippingFeature.find()) {
//				FeatureLog feature = findFeatureForFeature(mSkippingFeature
//						.group(1), projects);
//				if( feature != null) feature.skipped++;
//			}
//			// If I wanted to, I could also check for the plugins/* and then find the
//			// feature for each plug-in and record that information as well. At the
//			// moment I am assuming that a signed feature jar <=> signed plugins jars.
//		}
//	}

	public FeatureLog findFeatureForFeature(String featureName,
			List<ProjectLog> projects) {
		for (Iterator<ProjectLog> iterator = projects.iterator(); iterator
				.hasNext();) {
			ProjectLog project = iterator.next();
			for (Iterator<FeatureLog> iterator2 = project.features.iterator(); iterator2
					.hasNext();) {
				FeatureLog feature = iterator2.next();
				if (feature.feature.equals(featureName))
					return feature;
			}
		}
		return null;
	}
}
