//   Copyright 2012 Georg-August-Universität Göttingen, Germany
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

package de.ugoe.cs.autoquest.log4j;

import java.util.logging.Level;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import de.ugoe.cs.util.console.Console;
import de.ugoe.cs.util.console.listener.ICommandListener;
import de.ugoe.cs.util.console.listener.IErrorListener;
import de.ugoe.cs.util.console.listener.IExceptionListener;
import de.ugoe.cs.util.console.listener.ITraceListener;

/**
 * <p>
 * Implements logging based on the log4j API.
 * </p>
 * 
 * @author Steffen Herbold
 * @version 1.0
 */
public class Log4JLogger implements IErrorListener, ITraceListener, IExceptionListener,
    ICommandListener
{

    /**
     * <p>
     * Reference to the logger.
     * </p>
     */
    Logger logger;

    /**
     * <p>
     * This is the trace level according to the Java logger API. We use this instead of the log4j
     * levels themselves for the logging.
     * </p>
     */
    Level traceLevel;

    /**
     * <p>
     * Constructor. Creates a new Log4JLogger and registers the implemented listener with the
     * {@link Console}.
     * </p>
     * @param traceLevel tracing level
     */
    public Log4JLogger(Level traceLevel) {
        PropertyConfigurator.configure("data/log4j.properties");
        logger = Logger.getLogger("de.ugoe.cs.autoquest");
        logger.setLevel(convertToLog4JLevel(traceLevel));
        this.traceLevel = traceLevel;
        Console.getInstance().registerErrorListener(this);
        Console.getInstance().registerTraceListener(this);
        Console.getInstance().registerExceptionListener(this);
        Console.getInstance().registerCommandListener(this);
    }

    /*
     * (non-Javadoc)
     * 
     * @see de.ugoe.cs.util.console.listener.ICommandListener#commandNotification (java.lang.String)
     */
    @Override
    public void commandNotification(String command) {
        logger.info("Command executed: " + command);
    }

    /*
     * (non-Javadoc)
     * 
     * @see de.ugoe.cs.util.console.listener.IExceptionListener#printStacktrace(java
     * .lang.Exception)
     */
    @Override
    public void logException(Exception e) {
        logger.error("", e);
    }

    /*
     * (non-Javadoc)
     * 
     * @see de.ugoe.cs.util.console.listener.ITraceListener#traceMsg(java.lang.String )
     */
    @Override
    public void traceMsg(String traceMessage, Level level) {
        if( level.intValue()>=traceLevel.intValue()) {
            logger.log(convertToLog4JLevel(level), traceMessage);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see de.ugoe.cs.util.console.listener.IErrorListener#errorMsg(java.lang.String )
     */
    @Override
    public void errorMsg(String errMessage) {
        logger.error(errMessage);
    }

    /**
     * <p>
     * Converts the log level described by {@link Level} into a {@link org.apache.log4j.Level}.
     * </p>
     * 
     * @param level
     *            java.util.logger.Level severity
     * @return org.apache.log4j.Level severity
     */
    private org.apache.log4j.Level convertToLog4JLevel(Level level) {
        if (level == Level.OFF) {
            return org.apache.log4j.Level.OFF;
        }
        if (level == Level.SEVERE) {
            return org.apache.log4j.Level.FATAL;
        }
        if (level == Level.WARNING) {
            return org.apache.log4j.Level.WARN;
        }
        if (level == Level.INFO || level == Level.CONFIG) {
            return org.apache.log4j.Level.INFO;
        }
        // remaining levels: FINE, FINER, FINEST, ALL
        return org.apache.log4j.Level.ALL;
    }
}
