package org.eclipse.ganymede.webgen;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class Status implements Cloneable {
	public enum SType {
		Fail, Success, Information, Unknown
	};

	public static Status unknown = new Status("unable to determine status",
			SType.Unknown);

	public static Status success = new Status("Success", SType.Success, 500);

	public static Status internal_error = new Status("ganymatic system error",
			SType.Fail, 10);

	// private static Status fail = new Status("Fail", SType.Fail, 1000);
	public static Status getFail() {
		return new Status("Fail", SType.Fail, 1000);
	}

	public static Status information = new Status("unknown", SType.Information);

	private String string;
	private Set<Blame> blame;
	private boolean hasEmptyBlame = false;
	private int badness;
	private SType stype;
	public String error_bookmark;

	public Status(String s, SType t) {
		this.string = s;
		this.badness = 500;
		this.stype = t;
		this.error_bookmark = null;
		this.blame = new HashSet<Blame>();
	}

	public Status(String s, SType t, int b) {
		this.string = s;
		this.badness = b;
		this.stype = t;
		this.error_bookmark = null;
		this.blame = new HashSet<Blame>();
	}

	public boolean isFail() {
		return this.stype == SType.Fail;
	}

	Status moreSpecificFail(Status other) throws CloneNotSupportedException {
		if (this.isFail() && other.isFail()) {
			if (this.badness < other.badness)
				return (Status) this.clone();
			else
				return (Status) other.clone();
		}
		if (this.isFail())
			return (Status) this.clone();
		if (other.isFail())
			return (Status) other.clone();
		throw new Error("badness 10,000 " + this + " " + other);
	}

	public boolean isInformation() {
		return this.stype == SType.Information;
	}

	public boolean isSuccess() {
		return this.stype == SType.Success;
	}

	public Status combine(Status other) throws CloneNotSupportedException {
		// Status: Fail > Success > Unknown > Information

		Status newstatus = new Status("unknown", SType.Unknown);
		if (this.isFail() || other.isFail()) {
			newstatus = moreSpecificFail(other);
			newstatus.combineErrorBookmarks(this, other);
			newstatus.combineBlame(this, other);
		} else if (this.isSuccess())
			newstatus = this;
		else if (other.isSuccess())
			newstatus = (Status) other.clone();
		else if (this.isInformation())
			newstatus = this;
		else if (other.isInformation())
			newstatus = (Status) other.clone();
		else
			newstatus = this;

		return newstatus;
	}

	void combineErrorBookmarks(Status one, Status two) {
		if (one.error_bookmark != null) {
			this.error_bookmark = one.error_bookmark;
		} else {
			if (two.error_bookmark != null) {
				this.error_bookmark = two.error_bookmark;
			}
		}
	}

	void combineBlame(Status one, Status two) {
		if (one.blame.isEmpty()) {
			if (two.blame.isEmpty()) {
				// no change
			} else {
				this.blame = two.blame;
			}
		} else {
			if (two.blame.isEmpty()) {
				this.blame = one.blame;
			} else {
				this.blame = new HashSet<Blame>();
				this.blame.addAll(one.blame);
				this.blame.addAll(two.blame);
			}
		}
		if( one.hasEmptyBlame || two.hasEmptyBlame )
			this.hasEmptyBlame = true;
	}

	public void setErrorBookmark(String s) {
		this.error_bookmark = s;
	}

	public void setBlame(Blame b) {
		this.blame = new HashSet<Blame>(1);
		if (b != null)
			this.blame.add(b);
		else
			this.hasEmptyBlame = true;
	}

	public String getFailureEmailAddressesString() {
		if (this.blame == null)
			return "";
		Set<String> emails = new HashSet<String>();
		for (Iterator<Blame> iterator = this.blame.iterator(); iterator
				.hasNext();) {
			Blame blame = iterator.next();
			emails.addAll(blame.getFailureEmailAddresses());
			if( blame.getFailureEmailAddresses().isEmpty())
				this.hasEmptyBlame = true;
		}
		String result = "";
		for (Iterator<String> iterator = emails.iterator(); iterator.hasNext();) {
			String string = iterator.next();
			result += "," + string;
		}
		if( this.hasEmptyBlame )
			result += ",${ganymatic.releng.email}";
		if( result.length() > 1 )
			result = result.substring(1);
		return result;
	}

	public String toString() {
		if (this.isFail()) {
			if (!this.blame.isEmpty()) {
				String tmp = "";
				for (Iterator<Blame> iterator = this.blame.iterator(); iterator
						.hasNext();) {
					Blame blame = iterator.next();
					tmp += ", " + blame.stringForStatusMessage();
				}
				return this.string + " (" + tmp.substring(2) + ")";
			} else
				return this.string;
		} else {
			return this.string;
		}
	}

	public String color() {
		if (this.isFail())
			return WebPageColors.fail_color();
		if (this.isSuccess())
			return WebPageColors.success_color();
		if (this.isInformation())
			return WebPageColors.information_color();
		return WebPageColors.inprogress_color();
	}
}
