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;

public class ProjectLog {
	public String project;
	public String responsible;
	public Status status;
	public List<LogLine> lines;
	public List<FeatureLog> features;
	public ProjectLog( String p, String r ) {
		this.project = p;
		this.responsible = r;
		lines = new ArrayList<LogLine>();
	}
	public Status scan_for_status() {
		status = Status.unknown;
		for (Iterator<FeatureLog> iter = features.iterator(); iter.hasNext();) {
			FeatureLog feature = iter.next();
			feature.scan_for_status();
			status = status.combine( feature.status );
		}
		return status;
	}
	public void scanForPack200Status( List<ProjectLog> projects ) {
//		for (Iterator<FeatureLog> iter = features.iterator(); iter.hasNext();) {
//			FeatureLog feature = iter.next();
//			feature.scanForPack200Status( projects );
//		}
	}

	public void annotate_features_with_license_information(List<ProjectLog> projects) {
		Pattern feature_pat = Pattern.compile("\\sF\\s+(\\S+)\\.jar\\s+(\\S.+)");
		Pattern plugin_pat = Pattern
				.compile("\\sP\\s+(\\S+)\\.jar\\s+(\\S+)\\.jar\\s+(\\S.+)");
		for (Iterator<LogLine> iterator = this.lines.iterator(); iterator
				.hasNext();) {
			LogLine line = iterator.next();
			Matcher feature_m = feature_pat.matcher(line.line);
			Matcher plugin_m = plugin_pat.matcher(line.line);
			if (feature_m.find()) {
				if( !annotate_feature_with_license_information(projects, feature_m.group(1),
						feature_m.group(1) + ": " + feature_m.group(2)) ) {
					line.status = Status.fail;
				}
			} else if (plugin_m.find()) {
				if( !annotate_feature_with_license_information(projects, plugin_m.group(1),
						plugin_m.group(2) + ": " + plugin_m.group(3)) ) {
					line.status = Status.fail;
				}
			}
		}
	}

	boolean annotate_feature_with_license_information(List<ProjectLog> projects, String featureid, String text) {
		for (Iterator<ProjectLog> iterator = projects.iterator(); iterator
				.hasNext();) {
			ProjectLog project = iterator.next();
			for (Iterator<FeatureLog> iter2 = project.features.iterator(); iter2
					.hasNext();) {
				FeatureLog feature = iter2.next();
				String fid = feature.feature + "_" + feature.version;
				if (featureid.equals(fid)) {
					project.add_license_errors_feature("License Error: "
							+ text);
					return true;
				}
			}
		}
		return false;
	}

	void add_license_errors_feature(String text) {
		for (Iterator<FeatureLog> iter2 = this.features.iterator(); iter2
				.hasNext();) {
			FeatureLog feature = iter2.next();
			if (feature.feature.equals("license errors")) {
				feature.lines.add(new LogLine(text, feature.lines.size() + 1));
				return;
			}
		}
		FeatureLog feature = new FeatureLog(this, "license errors", "");
		feature.lines = new ArrayList<LogLine>();
		feature.lines.add(new LogLine(text, feature.lines.size() + 1));
		this.features.add(feature);
	}
	public void divide_into_features() {
		features = new ArrayList<FeatureLog>();
		FeatureLog current = new FeatureLog( this, "prefix", "");
		features.add(current);
		Pattern p1 = Pattern.compile("\\[echo\\] Updating ([\\w\\.]+) ([0-9\\.\\w\\-]+)");		
		Pattern p2 = Pattern.compile("init:");
		Pattern p3 = Pattern.compile(" Output to:");
		int start = 0;
		int end = 0;
		Iterator<LogLine> iter = lines.iterator();
		int i = 0;
		while( iter.hasNext() ) {
			LogLine line = iter.next();
			Matcher m1 = p1.matcher(line.line);
			Matcher m2 = p2.matcher(line.line);
			Matcher m3 = p3.matcher(line.line);
			if( m1.find() ) {
				if( start == end ) 
					end = i;
				current.lines = lines.subList(start, end);
				start = end;
				end = start;
				current = new FeatureLog( this, m1.group(1), m1.group(2) );
				features.add(current);
			}
			if( m2.matches() || m3.matches() ) 
				end = i;
			i++;
		}
		end = i;
		current.lines = lines.subList(start, end);
		
		if( current.feature == "prefix" )
			current.feature = current.project.project;
	}
}
