package cz.cuni.amis.pogamut.base.utils.logging;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Instance that serves as a gateway for your log messages.
 * <p><p>
 * The trick with categories is that every log record may contain
 * object parameters. So we're appending instance of this class as
 * a very first parameter to the log record and filter those messages
 * according to them.
 * 
 * @author Jimmy
 *
 */
public class LogCategory extends Logger {
	
	private String categoryName;
	
	public LogCategory(String categoryName) {
		super(categoryName, null);
		this.categoryName = categoryName;
	}
	
	public String getCategoryName() {
		return categoryName;
	}
	
	/**
	 * Returns new LogHandler with null ILogPublisher that is appended
	 * to the logger and filters log messages for this category.
	 * <p><p>
	 * The handler will use LogPublisher.ConsolePublisher as default.
	 * <p><p>
	 * This is the quickest way to obtain new output from the log. 
	 * 
	 * @return
	 */
	public LogHandler newHandler() {
		return newHandler(null);
	}
	
	/**
	 * Returns new LogHandler with specified ILogPublisher that is appended
	 * to the logger and filters log messages for this category.
	 * <p><p>
	 * The handler will use LogPublisher.ConsolePublisher as default.
	 * <p><p>
	 * This is the quickest way to obtain new output from the log. 
	 * 
	 * @return
	 */
	public LogHandler newHandler(ILogPublisher publisher) {
		LogHandler handler = new LogHandler();
		handler.setFilter(new LogCategoryFilter(this));
		handler.setPublisher(publisher);
		this.addHandler(handler);
		return handler;
	}
		
	public void log(Level level, String msg) {
		log(level, msg, new Object[0]);
	}
	
	public void log(Level level, String msg, Object param) {
		log(level, msg, new Object[]{param});
	}
	
	/**
	 * All other logging methods is calling this.
	 */
	public void log(Level level, String msg, Object[] params) {
		if (params.length == 0) {
			super.log(level, msg, this);
		} else {
			Object[] finalParams = new Object[params.length+1];
			finalParams[0] = this;
			System.arraycopy(params, 0, finalParams, 1, params.length);
			super.log(level, msg, finalParams);
		}
	}
	
	public void finest(String msg) {
		log(Level.FINEST, msg);
	}
	
	public void finest(String msg, Object param) {
		log(Level.FINEST, msg, param);
	}
	
	public void finest(String msg, Object[] params) {
		log(Level.FINEST, msg, params);
	}
	
	public void finer(String msg) {
		log(Level.FINER, msg);
	}
	
	public void finer(String msg, Object param) {
		log(Level.FINER, msg, param);
	}
	
	public void finer(String msg, Object[] params) {
		log(Level.FINER, msg, params);
	}
	
	public void fine(String msg) {
		log(Level.FINE, msg);
	}
	
	public void fine(String msg, Object param) {
		log(Level.FINE, msg, param);
	}
	
	public void fine(String msg, Object[] params) {
		log(Level.FINE, msg, params);
	}
	
	public void info(String msg) {
		log(Level.INFO, msg);
	}
	
	public void info(String msg, Object param) {
		log(Level.INFO, msg, param);
	}
	
	public void info(String msg, Object[] params) {
		log(Level.INFO, msg, params);
	}
	
	public void warning(String msg) {
		log(Level.WARNING, msg);
	}
	
	public void warning(String msg, Object param) {
		log(Level.WARNING, msg, param);
	}
	
	public void warning(String msg, Object[] params) {
		log(Level.WARNING, msg, params);
	}
	
	public void severe(String msg) {
		log(Level.SEVERE, msg);
	}
	
	public void severe(String msg, Object param) {
		log(Level.SEVERE, msg, param);
	}
	
	public void severe(String msg, Object[] params) {
		log(Level.SEVERE, msg, params);
	}
	
	public String toString() {
		return "LogCategory("+getName()+")";
	}

}
