package me.blackphreak.Debug;

import java.util.Arrays;

public class Debug {
	/**
	 * Debug Class
	 *
	 * log output:
	 * private log(...) -> "[+][ClassName->MethodName()@LineNumber] Message"
	 */
	private static int _currDebugLevel = DebugLevel.ALL.getLevel();
	
	private static final String _callerFormat = "%s->%s()@%d";
	private static final String _logFormat = "[%s][%s] %s";
	
	private static String formatCaller(StackTraceElement t) {
		return String.format(_callerFormat,
				t.getClassName(),
				t.getMethodName(),
				t.getLineNumber()
		);
	}
	
	// ---- Setter & Getter ----
	public static int getCurrentDebugLevel() {
		return _currDebugLevel;
	}
	
	public static void getCurrentDebugLevel(int currDebugLevel) {
		Debug._currDebugLevel = currDebugLevel;
	}
	
	// ---- Base Function ----
	
	/**
	 * Compare current debug level with the targeted DebugLevel,
	 *      if greater, make the log.
	 * @return make the log or not.
	 */
	private static boolean isLogLevelMatch(int lv) {
		return (_currDebugLevel & lv) > 0;
	}
	
	/**
	 * Log message with caller information
	 * @param lv log level
	 * @param offset stack trace offset value
	 * @param msg log message
	 */
	public static void log(int lv, int offset, String msg)
	{
		if (!isLogLevelMatch(lv))
			return;
		
		// add 1 offset to get the upper function
		StackTraceElement t = Thread.currentThread().getStackTrace()[offset + 1];
		
		System.out.printf(_logFormat,
				DebugLevel.getLowest(lv).getSymbol(),
				formatCaller(t),
				msg + "\n"
		);
	}
	
	/**
	 * Log multi-message with caller information
	 * @param lv log level
	 * @param offset stack trace offset value
	 * @param msgs log messages
	 */
	public static void logs(int lv, int offset, String... msgs)
	{
		if (!isLogLevelMatch(lv))
			return;
		
		// add 1 offset to get the upper function
		StackTraceElement t = Thread.currentThread().getStackTrace()[offset + 1];
		
		final String header = String.format(_logFormat,
				DebugLevel.getLowest(lv).getSymbol(),
				formatCaller(t),
				""
		);
		
		System.out.print(header + msgs[0] + "\n");
		
		// create padding spaces for rest of the messages
		final String prepend = " ".repeat(header.length() - 2);
		
		// skip the first printed message & print rest of the messages
		Arrays.stream(msgs).skip(1)
				.forEach(msg -> System.out.println(" |" + prepend + msg));
	}
	
	
	public static void info(String msg) {
		log(DebugLevel.INFO.getLevel(), 2, msg);
	}
	
	public static void warn(String msg) {
		log(DebugLevel.WARN.getLevel(), 2, msg);
	}
	
	public static void err(String msg) {
		log(DebugLevel.ERR.getLevel(), 2, msg);
	}
}