package com.prolixtech.utils;

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

import com.prolixtech.jaminid.Request;


/**
 * This class provides a single logging utility used for debugging purposes. It
 * delegates most of its work to the java logging system, however it is made a
 * singleton here so that it can be used throughout the application.
 * 
 * @author Constantinos Michael
 * 
 * 
 */
public class JavaLogger implements MboxLogger {

    private Logger logger;


    private static JavaLogger theInstance;

    private Handler consoleLog = new java.util.logging.ConsoleHandler();

    private boolean baloonsDisabled = false;

    /**
     * Pertains to the Singleton DESIGN PATTERN.
     * 
     * @return the singleton instance
     */
    public static MboxLogger Instance() {
        if (theInstance == null)
            theInstance = new JavaLogger();
        return theInstance;

    }


    protected JavaLogger() {

        this.logger = Logger.getLogger("ProlixLogger");
        logger.setLevel(Level.FINEST);
        logger.setUseParentHandlers(false);

        consoleLog.setLevel(Level.INFO);
        Formatter logFormat = new com.prolixtech.utils.SingleLineFormatter();
        this.consoleLog.setFormatter(logFormat);
        logger.addHandler(consoleLog);
        logger.log(Level.INFO, "The Logger service has started");

    }

    /**
     * For manual submission directly to the logger
     * 
     * @return the logger of this singleton
     */
    public Logger getLogger() {
        return logger;
    }

    /**
     * The main logging function is set by default to output to the console. If
     * we require better logging in the future, perhaps a number of streams will
     * be made. The default operation prints the last function called (gets it
     * through a stacktrace) the message, the time.
     * 
     * @param vel
     *            the level of the message to log.
     * @see java.util.logging.Level
     * @param msg
     *            the message to log.
     */
    public void log(Level vel, String msg) {

        StackTraceElement[] astrel = (new Throwable()).getStackTrace();

        String callingClass = "";

        for (int i = 0; i < astrel.length; i++) {
            StackTraceElement strel = astrel[i];
            callingClass = (strel.getClassName());
            if (!callingClass.endsWith(".SingletonLogger"))
                break;
        }

        callingClass = callingClass
                .substring(callingClass.lastIndexOf(".") + 1);

        logger.log(vel, "[" + callingClass + "] " + msg);

    }

    /*
     * The following specialized logging levels permit submission of messages
     * without importation of java.util.logging
     */

    /**
     * Shortcut to submit a log message at the level FINE
     * 
     * @param msg
     *            the message to submit
     */
    public void fine(String msg) {
        log(Level.FINE, msg);
    }

    /**
     * Shortcut to submit a log message at the level SEVERE
     * 
     * @param msg
     *            the message to submit
     */
    public void severe(String msg) {
        log(Level.SEVERE, msg);
    }

    /**
     * Shortcut to submit a log message at the level WARNING
     * 
     * @param msg
     *            the message to submit
     */
    public void warning(String msg) {
        log(Level.WARNING, msg);
    }

    /**
     * Shortcut to submit a log message at the level INFO
     * 
     * @param msg
     *            the message to submit
     */
    public void info(String msg) {
        log(Level.INFO, msg);
    }

    /*
     * following are specialized levels that enable categorization into types of
     * messages.
     */

    /**
     * Specialized submit for SQL messages
     * 
     * @param msg
     *            the message to submit
     */
    public void sql(String msg) {
        log(Level.FINEST, "[SQL] " + msg);
    }

    /**
     * Specialized submit for HTTP messages
     * 
     * @param msg
     *            the message to submit
     */
    public void http(Request req, String msg) {
        log(Level.INFO, "[HTTP " + req.getIPAddressString() + "]" + msg);
    }

    /**
     * 
     */
    public void disableBaloons() {
        this.baloonsDisabled = true;
    }

    public void exception(Level x, String msg, Exception e) {
        log(x, msg);
        e.printStackTrace();
    }

    public void exception(String msg, Exception e) {
        this.exception(Level.WARNING, msg, e);
    }


    /* (non-Javadoc)
     * @see com.prolixtech.utils.MboxLogger#baloon(java.lang.String, java.lang.String)
     */
    public void baloon(String msg, String title) {
        this.info(title + " : " + msg);
        
    }

}