package ash.util;

import java.io.PrintStream;

/**
 * ユーティリティメソッド
 */
public class Log {
	static final PrintStream STDERR = System.err; // 起動端末の標準エラー
	static PrintStream err = System.err;

	static private void printTrace(int level, String message) {
		((level < 0) ? STDERR : err).println(message);
	}
	/* デバッグメッセージの表示制御
	 * debugLevelの値によって　debug(level, ...) と trace(level, ) による
	 * メッセージ表示を制御する。
	 *  debugLevel <  10   の場合：level <= debugLevel ならば表示する
	 *  debugLevel >= 10   の場合：
	 *    debugLevel/10 == level/10 の場合：
	 *      １桁目の数字が同じか片方が0ならば表示する。
	 *    それ以外の場合は表示しない
	 */
	private static int debugLevel = 0;
	public static boolean check(int level) {
		if(level < 0) level = -level;
		if(debugLevel < 10) return (level <= debugLevel);
		if(debugLevel/10 == level/10) {
			int d = debugLevel % 10;
			int l = level % 10;
			return (d == 0 || l == 0 || d == l);
		}
		return false;
	}
	/**
	 * デバッグレベルを取得する。
	 */
	public static int getDebugLevel() {
		return debugLevel;
	}
	/**
	 * デバッグレベルを設定する。
	 * @param level デバッグレベル
	 * <p> level < 0  の場合: 起動端末へ表示する。
	 */
	public static void setDebugLevel(int level) {
		if(level >= 0) {		// AshConsole へ表示
			err = System.err;
		} else if(level < 0) {	// 起動端末へ表示
			level = -level;
			err = STDERR;
		}
		debugLevel = level;
		assert debug(9,    "デバッグレベル 9");
		assert debug(100,  "デバッグレベル 100");
		assert debug(101,  "デバッグレベル 101");
		assert debug(109,  "デバッグレベル 109");
		assert debug(-101, "デバッグレベル -101");
	}
	/**
	 * デバッグ表示レベルに応じてデバッグ行を表示する
	 * @param level 表示レベル（負の場合は起動端末へ表示）
	 * @param message デバッグ行
	 */
	public static boolean debug(int level, String message) {
		if(check(level)) printTrace(level, message);
		return true;
	}
	/**
	 * Throwabel(Exception/Error)を表示する。
	 * @param e 例外やエラー
	 */
	public static boolean debug(Throwable e) {
		if(debugLevel == 0) {
			printTrace(0, e.toString());
		} else {
			e.printStackTrace(err);
		}
		return true;
	}
	/**
	 * デバッグ行とThrowable を表示する。
	 */
	public static boolean debug(Throwable e, int level, String message) {
		debug(level, message);
		debug(e);
		return true;
	}
	/**
	 * デバッグ表示レベルに応じてスレッドと共にトレース文を表示する。
	 * @param level 表示レベル（負の場合は起動端末へ表示）
	 * @param message デバッグ行
	 */
	public static boolean trace(int level, String message) {
		if(check(level)) printTrace(level, "" + thread() + " " + message);
		return true;
	}
	public static boolean trace(int level, String message, Thread th) {
		return trace(level, message + thread(th));
	}
	public static String thread() {
		//return Thread.currentThread().toString().substring(6);
		return thread(Thread.currentThread());
	}
	public static String thread(Thread th) {
		return String.format("[%-6s]", th.getName());
	}
}
