package org.biomoby.registry.rdfagent.util;

import java.io.IOException;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import org.biomoby.shared.Utils;

/**
 * A logging class for the agent.
 * 
 * @author Edward Kawas
 * 
 */
public class Log {

	private static Logger logger = null;

	private static boolean isInit = false;

	private static Level level = Level.INFO;

	/**
	 * log all messages
	 */
	public static final Level ALL = Level.ALL;
	
	/**
	 * log only info messages
	 */
	public static final Level INFO = Level.INFO;

	/**
	 * log warning messages
	 */
	public static final Level WARN = Level.WARNING;

	/**
	 * log severe messages
	 */
	public static final Level SEVERE = Level.SEVERE;

	private static boolean enabled = true;
	
	private static void setLogLevel(Level logLevel) {
		Log.level = logLevel;
		// create an initialize a logger
		logger.setLevel(logLevel);
		info("Logging level set to " + logLevel.getName());
	}

	/*
	 * a method to initialize the logger
	 */
	private static void init(String path) {
		logger = Logger.getLogger("org.biomoby.registry.rdfagent");
		// following ensures that only one log file is created.
		if (isInit) {
			return;
		}
		isInit = true;
		try {
			Calendar calendar = new GregorianCalendar();

			String logDirectory = path;
			// log files will be created based on mm-dd-yyyy - hh:mm
			String logFile = "AgentLog-" + (calendar.get(Calendar.MONTH)+1) + "-"
					+ calendar.get(Calendar.DAY_OF_MONTH) + "-"
					+ calendar.get(Calendar.YEAR) + "-"
					+ calendar.get(Calendar.HOUR_OF_DAY) + "_"
					+ calendar.get(Calendar.MINUTE);
			FileHandler fh = new FileHandler(logDirectory + logFile + ".log",
					true);
			fh.setFormatter(new SimpleFormatter());
			logger.addHandler(fh);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * @param logPath
	 *            the directory to place the log file
	 * @param level
	 *            the level of loggin that you would like have.
	 * @param msg
	 *            the message to log upon starting
	 */
	public static void start(String logPath, Level level, boolean enable, String msg) {
		enabled = enable;
		if (enabled) {
			Log.init(logPath);
			info(msg);
			Log.setLogLevel(level);
		}
	}

	/**
	 * A method to stop logging.
	 * 
	 * @param msg
	 *            a message to output
	 */
	public static void stop(String msg) {
		if (enabled) {
			logger.setLevel(Log.INFO);
			info(msg);
		}
	}

	/**
	 * 
	 * @param msg
	 *            the string that you would like to log as a warning
	 */
	public static void warning(String msg) {
		if (enabled)
			if (logger.isLoggable(Log.WARN))
				logger.warning(Utils.format(System.getProperty("line.separator")+ "\t"+msg + System.getProperty("line.separator"),3));
	}

	/**
	 * 
	 * @param msg
	 *            the string that you would like to log as info
	 */
	public static void info(String msg) {
		if (enabled)
			if (logger.isLoggable(Log.INFO))
				logger.info(Utils.format(System.getProperty("line.separator")+ "\t"+msg + System.getProperty("line.separator"),3));
	}

	/**
	 * 
	 * @param msg
	 *            the string that you would like to log as severe
	 */
	public static void severe(String msg) {
		if (enabled)
			if (logger.isLoggable(Log.SEVERE))
				logger.severe(Utils.format(System.getProperty("line.separator")+ "\t"+msg + System.getProperty("line.separator"),3));
	}

	/**
	 * 
	 * @param cls
	 *            the class where the exception occured
	 * @param method
	 *            the method that caused the exception
	 * @param t
	 *            the throwable object to log
	 */
	public static void exception(String cls, String method, Throwable t) {
		if (enabled)
			logger.throwing(cls, method, t);
	}

	/**
	 * 
	 * @return whether or not the the logger can log.
	 */
	public static boolean isLoggable() {
		return (Log.logger != null);
	}

	/**
	 * 
	 * @param enabled if true, then logging is set to enabled, otherwise it is not
	 */
	public static void setEnabled(boolean enabled) {
		Log.enabled = enabled;
	}
}
