/**
 *  Licensed under GPL. For more information, see
 *    http://jaxodraw.sourceforge.net/license.html
 *  or the LICENSE file in the jaxodraw distribution.
 */
package net.sf.jaxodraw.util;

import java.util.logging.Level;

import net.sf.jaxodraw.logging.JaxoDefaultLogger;
import net.sf.jaxodraw.logging.JaxoLogger;

/** Some custom methods to handle error messages.
 * @since 2.0
 */
public final class JaxoLog {
    /** DEBUG logging level (most verbose).  */
    public static final int DEBUG = Level.FINE.intValue();

    /** INFO logging level (default).  */
    public static final int INFO = Level.INFO.intValue();

    /** WARN logging level (least verbose).  */
    public static final int WARN = Level.WARNING.intValue();

      //
     // private
    //

    private static JaxoLogger logger = new JaxoDefaultLogger(JaxoInfo.LOG_DIR);


    /** Do not instantiate. */
    private JaxoLog() {
        // empty on purpose
    }

    /**
     * Returns the current logger.
     *
     * @return a JaxoLogger.
     */
    public static JaxoLogger getLogger() {
        return logger;
    }

    /**
     * Sets a logger. If this is not called explicitly, a default logger will
     * be used by JaxoDraw. Set this to null to completely disable any logging.
     *
     * @param newLogger a JaxoLogger.
     */
    public static void setLogger(final JaxoLogger newLogger) {
        if (newLogger == null) {
            logger = new DevNullLogger();
        } else {
            logger = newLogger;
        }
    }

    /**
     * Sets the logging level.
     *
     * @param level One of the levels defined by this class.
     */
    public static void setLevel(final int level) {
        logger.setLevel(getLevelFor(level));
    }

    /**
     * Gets the current logging level.
     *
     * @return One of the levels defined by this class.
     */
    public static int getCurrentLevel() {
        return logger.getLevel().intValue();
    }

    /**
     * Check if a message of the given level would actually
     * be logged by the current logger.
     *
     * @param level One of the levels defined by this class.
     * @return true if the given message level is currently being logged.
     */
    public static boolean isLoggable(final int level) {
        return logger.isLoggable(getLevelFor(level));
    }

      //
     // DEBUG
    //

    /** Logs a DEBUG message.
     * @param message The log message.
     */
    public static void debug(final String message) {
        log(Level.FINE, message, null);
    }

    /** Logs a DEBUG message.
     * The actual message is looked up in one of the resource bundles
     * defined by JaxoDraw via the given messageKey.
     * @param messageKey The ResourceBundle key to look up the log message.
     */
    public static void debugI18N(final String messageKey) {
        logI18N(Level.FINE, messageKey, null);
    }

    /** Logs a DEBUG message.
     * @param message The log message.
     * @param e An exception to be appended to the message.
     */
    public static void debug(final String message, final Exception e) {
        log(Level.FINE, message, e);
    }

    /** Logs a DEBUG message.
     * The actual message is looked up in one of the resource bundles
     * defined by JaxoDraw via the given messageKey.
     * @param messageKey The ResourceBundle key to look up the log message.
     * @param e An exception to be appended to the message.
     */
    public static void debugI18N(final String messageKey, final Exception e) {
        logI18N(Level.FINE, messageKey, e);
    }

    /** Logs a DEBUG message.
     * @param e An exception to be logged.
     */
    public static void debug(final Exception e) {
        log(Level.FINE, null, e);
    }

      //
     // INFO
    //

    /** Logs an INFO message.
     * @param message The log message.
     */
    public static void info(final String message) {
        log(Level.INFO, message, null);
    }

    /** Logs an INFO message.
     * The actual message is looked up in one of the resource bundles
     * defined by JaxoDraw via the given messageKey.
     * @param messageKey The ResourceBundle key to look up the log message.
     */
    public static void infoI18N(final String messageKey) {
        logI18N(Level.INFO, messageKey, null);
    }

    /** Logs an INFO message.
     * @param message The log message.
     * @param e An exception to be appended to the message.
     */
    public static void info(final String message, final Exception e) {
        log(Level.INFO, message, e);
    }

    /** Logs an INFO message.
     * The actual message is looked up in one of the resource bundles
     * defined by JaxoDraw via the given messageKey.
     * @param messageKey The ResourceBundle key to look up the log message.
     * @param e An exception to be appended to the message.
     */
    public static void infoI18N(final String messageKey, final Exception e) {
        logI18N(Level.INFO, messageKey, e);
    }

    /** Logs an INFO message.
     * @param e An exception to be logged.
     */
    public static void info(final Exception e) {
        log(Level.INFO, null, e);
    }

      //
     // WARNING
    //

    /** Logs a WARNING message.
     * @param message The log message.
     */
    public static void warn(final String message) {
        log(Level.WARNING, message, null);
    }

    /** Logs a WARNING message.
     * The actual message is looked up in one of the resource bundles
     * defined by JaxoDraw via the given messageKey.
     * @param messageKey The ResourceBundle key to look up the log message.
     */
    public static void warnI18N(final String messageKey) {
        logI18N(Level.WARNING, messageKey, null);
    }

    /** Logs a WARNING message.
     * @param message The log message.
     * @param e An exception to be appended to the message.
     */
    public static void warn(final String message, final Exception e) {
        log(Level.WARNING, message, e);
    }

    /** Logs a WARNING message.
     * The actual message is looked up in one of the resource bundles
     * defined by JaxoDraw via the given messageKey.
     * @param messageKey The ResourceBundle key to look up the log message.
     * @param e An exception to be appended to the message.
     */
    public static void warnI18N(final String messageKey, final Exception e) {
        logI18N(Level.WARNING, messageKey, e);
    }

    /** Logs a WARNING message.
     * @param e An exception to be logged.
     */
    public static void warn(final Exception e) {
        log(Level.WARNING, null, e);
    }

      //
     // log with level
    //

    /** Logs a log message with given level.
     * @param level The log level.
     * @param message The log message.
     */
    public static void log(final int level, final String message) {
        log(getLevelFor(level), message, null);
    }

    /** Logs a log message with given level.
     * The actual message is looked up in one of the resource bundles
     * defined by JaxoDraw via the given messageKey.
     * @param level The log level.
     * @param messageKey The ResourceBundle key to look up the log message.
     */
    public static void logI18N(final int level, final String messageKey) {
        logI18N(getLevelFor(level), messageKey, null);
    }

    /** Logs a log message with given level.
     * @param level The log level.
     * @param message The log message.
     * @param e An exception to be appended to the message.
     */
    public static void log(final int level, final String message, final Exception e) {
        log(getLevelFor(level), message, e);
    }

    /** Logs a log message with given level.
     * The actual message is looked up in one of the resource bundles
     * defined by JaxoDraw via the given messageKey.
     * @param level The log level.
     * @param messageKey The ResourceBundle key to look up the log message.
     * @param e An exception to be appended to the message.
     */
    public static void logI18N(final int level, final String messageKey, final Exception e) {
        logI18N(getLevelFor(level), messageKey, e);
    }

    /** Logs a log message with given level.
     * @param level The log level.
     * @param e An exception to be logged.
     */
    public static void log(final int level, final Exception e) {
        log(getLevelFor(level), null, e);
    }

    /**
     * Converts JaxoLog levels to java.util.logging.Level.
     *
     * @param level A level defined by this class.
     * @return the corresponding java.util.logging.Level.
     */
    public static Level getLevelFor(final int level) {
        Level newLevel = null;
        if (level < INFO) {
            newLevel = Level.FINE;
        } else if (level < WARN) {
            newLevel = Level.INFO;
        } else {
            newLevel = Level.WARNING;
        }
        return newLevel;
    }

      //
     // private methods
    //

    private static void log(final Level level, final String message, final Exception e) {
        logger.log(level, message, e);
    }

    private static void logI18N(final Level level, final String messageKey, final Exception e) {
        log(level, JaxoLanguage.translate(messageKey), e);
    }

    private static class DevNullLogger implements JaxoLogger {
        /** {@inheritDoc} */
        public void setLevel(final Level level) {
            // nop
        }

        /** {@inheritDoc} */
        public Level getLevel() {
            return Level.OFF;
        }

        /** {@inheritDoc} */
        public boolean isLoggable(final Level level) {
            return false;
        }

        /** {@inheritDoc} */
        public void log(final Level level, final String message, final Throwable e) {
            // nop
        }
    }
}
