package nallar.tickthreading.log;

import java.io.*;
import java.text.*;
import java.util.logging.*;

public class LogFormatter extends Formatter {
	public static final String LINE_SEPARATOR = System.getProperty("line.separator");
	protected static final boolean colorEnabled = System.getProperty("colorLogs", "false").equalsIgnoreCase("true");
	private static final boolean simplifyMcLoggerName = !System.getProperty("fullLoggerName", "false").equalsIgnoreCase("true");
	private static SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd HH:mm:ss");

	public static void setFormat(SimpleDateFormat dateFormat) {
		if (dateFormat != null) {
			LogFormatter.dateFormat = dateFormat;
		}
	}

	private static String getColorForLevel(Level level) {
		return "\033[" + getColorNumberForLevel(level) + 'm';
	}

	private static String getColorNumberForLevel(Level level) {
		if (level == Level.SEVERE) {
			return "31";
		} else if (level == Level.WARNING) {
			return "33";
		} else if (level == DebugLevel.DEBUG) {
			return "35";
		} else if (level == Level.INFO) {
			return "32";
		}
		return "39";
	}

	protected static String getEndColor() {
		return "\033[39m";
	}

	protected boolean shouldColor() {
		return colorEnabled;
	}

	@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
	@Override
	public String format(LogRecord record) {
		StringBuilder formattedMessage = new StringBuilder();
		long millis = record.getMillis();
		String date;
		SimpleDateFormat dateFormat = LogFormatter.dateFormat;
		synchronized (dateFormat) {
			date = dateFormat.format(millis);
		}
		formattedMessage.append(date);
		Level level = record.getLevel();
		formattedMessage.append(" [");
		final boolean shouldColor = shouldColor();
		if (shouldColor) {
			formattedMessage.append(getColorForLevel(level));
		}
		formattedMessage.append(record.getLevel().getName().toUpperCase());
		if (shouldColor) {
			formattedMessage.append(getEndColor());
		}
		formattedMessage.append("] ");


		String loggerName = record.getLoggerName();
		String message = record.getMessage();
		if (simplifyMcLoggerName && loggerName.equals("Minecraft-Server")) {
			loggerName = "Minecraft";
		} else if (message.startsWith("[") && message.contains("]")) {
			loggerName = null;
		} else if (loggerName.contains(".")) {
			loggerName = loggerName.substring(loggerName.lastIndexOf('.') + 1);
		}
		if (loggerName != null) {
			formattedMessage.append('[').append(loggerName).append("] ");
		}

		formattedMessage.append(message).append(LINE_SEPARATOR);

		// No need to throw this, we're in a log formatter!
		@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
		Throwable throwable = record.getThrown();
		if (throwable != null) {
			if (throwable.getClass().getName().endsWith("ThreadStuckError")) {
				return "";
			}
			if (throwable.getStackTrace().length == 0) {
				formattedMessage.append("Stack trace unavailable for ").append(String.valueOf(throwable)).append('-').append(throwable.getClass().getName()).append(". Add -XX:-OmitStackTraceInFastThrow to your java parameters to see all stack traces.").append(LINE_SEPARATOR);
			} else {
				StringWriter stackTraceWriter = new StringWriter();
				// No need to close this - StringWriter.close() does nothing, and PrintWriter.close() just calls it.
				//noinspection IOResourceOpenedButNotSafelyClosed
				throwable.printStackTrace(new PrintWriter(stackTraceWriter));
				String output = stackTraceWriter.toString();
				if (throwable.getClass() == Throwable.class) {
					output = output.replace("java.lang.Throwable\n", "");
				}

				formattedMessage.append(output);
			}

			if (throwable.getCause() != null && throwable.getCause().getStackTrace().length == 0) {
				formattedMessage.append("Stack trace unavailable for cause: ").append(String.valueOf(throwable.getCause())).append('-').append(throwable.getCause().getClass().getName()).append(". Add -XX:-OmitStackTraceInFastThrow to your java parameters to see all stack traces.").append(LINE_SEPARATOR);
			}
		}

		return formattedMessage.toString();
	}
}

@@ -574,16 +574,20 @@
 void set
+Date
 Format(S
@@ -719,29 +719,26 @@
 ring get
+Start
 Color
-ForLevel
 (Level l
@@ -764,38 +764,32 @@
 033%5B%22 + getColor
-Number
 ForLevel(level) 
@@ -811,30 +811,27 @@
 vate static 
-Str
 in
-g
+t
  getColorNum
@@ -831,14 +831,8 @@
 olor
-Number
 ForL
@@ -896,12 +896,10 @@
 urn 
-%22
 31
-%22
 ;%0A%09%09
@@ -949,12 +949,10 @@
 urn 
-%22
 33
-%22
 ;%0A%09%09
@@ -1005,12 +1005,10 @@
 urn 
-%22
 35
-%22
 ;%0A%09%09
@@ -1055,12 +1055,10 @@
 urn 
-%22
 32
-%22
 ;%0A%09%09
@@ -1072,12 +1072,10 @@
 urn 
-%22
 39
-%22
 ;%0A%09%7D
@@ -1759,29 +1759,26 @@
 pend(get
+Start
 Color
-ForLevel
 (level))

Rename setFormat -> setDateFormat, getColorNumberForLevel -> getColorForLevel, getColorForLevel -> getStartColor