package ch.elexis.core.status;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.util.Arrays;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.slf4j.Logger;

import ch.elexis.core.jdt.NonNull;

// TODO refactor ...
public class StatusUtil {
	public static void printStatus(Logger log, IStatus status) {
		print(log, "", status);
	}

	public static void print(Logger log, String indent, IStatus status) {
		if (status.isMultiStatus()) {
			log.warn(indent + status.getMessage().replace('\n', ' '));
			String childIndent = indent + "  ";
			for (IStatus c : status.getChildren()) {
				print(log, childIndent, c);
			}
		} else {
			log.warn(indent + status.getMessage().replace('\n', ' '));
		}
	}

	public static void printStatus(PrintStream out, IStatus status) {
		print(out, "", status);
	}

	public static String printStatus(IStatus status) {
		try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
			PrintStream ps = new PrintStream(baos);
			printStatus(ps, status);
			return baos.toString(Charset.defaultCharset().toString());
		} catch (IOException e) {
			return e.getMessage();
		}
	}

	private static void print(PrintStream printStream, String indent, IStatus status) {
		if (status.isMultiStatus()) {
			printStream.print(indent + status.getMessage());
			String childIndent = indent + "  ";
			for (IStatus c : status.getChildren()) {
				print(printStream, childIndent, c);
			}
		} else if (status instanceof ObjectStatus) {
			ObjectStatus os = (ObjectStatus) status;
			printStream.println((os != null) ? os.getObject().toString() : null);
		} else {
			printStream.println(indent + status.getMessage());
		}
	}

	/**
	 * Create a Status.ERROR telling the user to search the logfile for explanation.
	 * 
	 * @param pluginId
	 * @return
	 */
	public static IStatus errorSeeLog(String pluginId) {
		return new Status(Status.ERROR, pluginId, "Execution error, see log.");
	}

	/**
	 * Log a status to the corresponding log-level; does nothing if
	 * {@link Status#isOK()}
	 * 
	 * @param prependMessage              an optional message to prepend the status
	 *                                    message
	 * @param log
	 * @param status
	 * @param includeExceptionIfAvailable
	 * @param logDebugIfOk                log to level debug if the status is ok
	 */
	public static void logStatus(String prependMessage, @NonNull Logger log, @NonNull IStatus status,
			boolean includeExceptionIfAvailable, boolean logDebugIfOk) {
		if (status.isOK() && !logDebugIfOk) {
			return;
		}

		StringBuilder sb = new StringBuilder();
		if (status.isMultiStatus()) {
			sb.append("[MULTISTATUS] ");
		}
		if (prependMessage != null) {
			sb.append(prependMessage + " ");
		}
		sb.append("(c" + status.getCode() + "/s" + status.getSeverity() + ") ");
		sb.append(status.getMessage());
		String message = sb.toString();

		boolean includeException = (includeExceptionIfAvailable && status.getException() != null);

		int severity = status.getSeverity();
		switch (severity) {
		case Status.ERROR:
			if (includeException) {
				log.error(message, status.getException());
			} else {
				log.error(message);
			}
			break;
		case Status.WARNING:
			if (includeException) {
				log.warn(message, status.getException());
			} else {
				log.warn(message);
			}
			break;
		case Status.INFO:
		case Status.CANCEL:
			if (includeException) {
				log.info(message, status.getException());
			} else {
				log.info(message);
			}
			break;
		case Status.OK:
			log.debug(message);
			break;
		default:
			break;
		}

		if (status.isMultiStatus()) {
			Arrays.asList(status.getChildren()).stream().forEach(c -> logStatus(prependMessage, log, c, true, false));
		}
	}

	/**
	 * convenience method, includes exception if available
	 * 
	 * @param log
	 * @param status
	 * @see #logStatus(String, Logger, IStatus, boolean, boolean)
	 */
	public static void logStatus(Logger log, IStatus status) {
		logStatus(null, log, status, true, false);
	}

	/**
	 * convenience method, includes exception if available
	 * 
	 * @param prependMessage
	 * @param log
	 * @param status
	 * @see #logStatus(String, Logger, IStatus, boolean, boolean)
	 */
	public static void logStatus(String prependMessage, Logger log, IStatus status) {
		logStatus(prependMessage, log, status, true, false);
	}

	/**
	 * convenience method, includes exception if available
	 * 
	 * @param log
	 * @param status
	 * @param includeExceptionIfAvailable
	 * @see #logStatus(String, Logger, IStatus, boolean, boolean)
	 */
	public static void logStatus(Logger log, IStatus status, boolean includeExceptionIfAvailable) {
		logStatus(null, log, status, includeExceptionIfAvailable, false);
	}

}

@@ -1361,26 +1361,124 @@
 %0A%09%09%09
-printStream.print(
+String severityString = getSeverityString(status.getSeverity());%0A%09%09%09printStream.print(%22%5B%22 + severityString + %22%5D %22 + 
 inde
@@ -1807,16 +1807,16 @@
  else %7B%0A
-
 %09%09%09print
@@ -1861,32 +1861,362 @@
 age());%0A%09%09%7D%0A%09%7D%0A%0A
+%09private static String getSeverityString(int severity) %7B%0A%09%09switch (severity) %7B%0A%09%09case Status.OK:%0A%09%09%09return %22OK%22;%0A%09%09case Status.WARNING:%0A%09%09%09return %22WARNING%22;%0A%09%09case Status.ERROR:%0A%09%09%09return %22ERROR%22;%0A%09%09case Status.INFO:%0A%09%09%09return %22INFO%22;%0A%09%09case Status.CANCEL:%0A%09%09%09return %22CANCEL%22;%0A%09%09default:%0A%09%09%09return %22? %22 + severity + %22 ?%22;%0A%09%09%7D%0A%09%7D%0A%0A
 %09/**%0A%09 * Create 

Update StatusUtil