package org.eclipse.europa.tools.webgen;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LogFileParser {
	public BufferedReader input;

	public List<ProjectLog> projects;
	public List<LogLine> lines;
	public Status status;

	public LogFileParser(File f) throws IOException {
		input = new BufferedReader(new FileReader(f));
	}

	public void parse() throws IOException {
		read_all_lines_into_memory();
		divide_into_projects();
		for (Iterator<ProjectLog> iterator = projects.iterator(); iterator
				.hasNext();) {
			ProjectLog project = iterator.next();
			project.divide_into_features();
		}
	}

	void scan_for_status() throws IOException {
		this.status = Status.unknown;
		for (Iterator<ProjectLog> iterator = projects.iterator(); iterator
				.hasNext();) {
			ProjectLog project = iterator.next();
			project.scan_for_status();
			this.status = this.status.combine(project.status);
		}
		if (this.status.isFail())
			this.status = Status.fail;
	}

	void read_all_lines_into_memory() throws IOException {
		lines = new ArrayList<LogLine>();
		String line = input.readLine();
		int num = 1;
		while (line != null) {
			LogLine logline = new LogLine(line, num++);
			lines.add(logline);
			line = input.readLine();
		}
	}

	void divide_into_projects() {
		/*
		 * This algorithm works by looking through the lines of the log
		 * file for special marker lines.  In general, it keeps three pointers:
		 * 
		 * ...
		 * ...
		 * ... <-- start (of the project I'm currently scanning)
		 * ... \
		 * ... |<-- (body of the project I'm currently scanning)
		 * ... /
		 * ... <-- potential_end (of the project I'm currently scanning)
		 * ... \
		 * ... |<-- (body of the next project)
		 * ... /
		 * ... <-- line_number (the current line)
		 * 
		 * This is because we don't know we're in a new project until we encounter
		 * the "Project:" header, but at the same time the beginning of the new
		 * project is the previous "update:" line before the Project: line.
		 */
		projects = new ArrayList<ProjectLog>();
		ProjectLog current = new ProjectLog("prefix", "");
		projects.add(current);
		Pattern p1 = Pattern
				.compile("\\[echo\\]\\s+\\-*\\s+Project:\\s+([\\w\\s_\\-\\.,]+)\\s+Responsible:\\s+(\\w+)");
		Pattern p2 = Pattern.compile("update:");
		Pattern p3 = Pattern.compile("^Total time:");
		int start_of_current_project = 0;
		int potential_end = 0;
		Iterator<LogLine> iter = lines.iterator();
		int line_number = 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 we've found a "Project:" line then we need
			 * to start a new project section.
			 */
			if (m1.find()) {
				/* special case for the first project in the file:
				 * we haven't seen the end of the previous project yet (because
				 * there isn't one), so the Project: line be the "end" of the
				 * non-existent previous project	 */
				if (start_of_current_project == potential_end)
					potential_end = line_number;
				/* save away the lines for the current project, i.e.,
				 * the one we were collecting for, not the one for which
				 * we've just seen the start line	 */
				current.lines = lines.subList(start_of_current_project, potential_end);
				/* the start of the next project section is the end
				 * of the current one */
				start_of_current_project = potential_end;
				/* the end of the next project cannot be earlier than
				 * it's beginning, so set it as well 		 */
				potential_end = start_of_current_project;
				/* start a new project with the new name, etc.
				 * We are now scanning lines for this project.		 */
				current = new ProjectLog(m1.group(1), m1.group(2));
				projects.add(current);
			}
			/*
			 * If we've found "update:" then it marks the potential
			 * end to the current project. We won't know that until
			 * we find a "Project:" line, but we record it as a
			 * potential end here.
			 */
			if (m2.matches() )
				potential_end = line_number;
			/*
			 * If we've found "Total time:" then the NEXT line is
			 * the potential end to the current project. Again, we 
			 * won't know that until...
			 */
			if (m3.find() )
				potential_end = line_number + 1;
			line_number++;
		}
		potential_end = line_number;
		current.lines = lines.subList(start_of_current_project, potential_end);
	}
}
