/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

/* $Id: CommandLineLogger.java 985537 2010-08-14 17:17:00Z jeremias $ */

package org.apache.fop.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * This is a commons-logging logger for command line use.
 */
public class CommandLineLogger implements Log {
    /** "Trace" level logging. */
    public static final int LOG_LEVEL_TRACE  = 1;
    /** "Debug" level logging. */
    public static final int LOG_LEVEL_DEBUG  = 2;
    /** "Info" level logging. */
    public static final int LOG_LEVEL_INFO   = 3;
    /** "Warn" level logging. */
    public static final int LOG_LEVEL_WARN   = 4;
    /** "Error" level logging. */
    public static final int LOG_LEVEL_ERROR  = 5;
    /** "Fatal" level logging. */
    public static final int LOG_LEVEL_FATAL  = 6;

    private int logLevel;
    private String logName;

    /**
     * Construct the logger with a default log level taken from the LogFactory
     * attribute "level".
     * @param logName the logger name.
     */
    public CommandLineLogger(String logName) {
        this.logName = logName;
        setLogLevel((String) LogFactory.getFactory().getAttribute("level"));
    }

    /**
     * Set a log level for the logger.
     * @param level the log level
     */
    public void setLogLevel(String level) {
        if ("fatal".equals(level)) {
            logLevel = LOG_LEVEL_FATAL;
        } else if ("error".equals(level)) {
            logLevel = LOG_LEVEL_ERROR;
        } else if ("warn".equals(level)) {
            logLevel = LOG_LEVEL_WARN;
        } else if ("info".equals(level)) {
            logLevel = LOG_LEVEL_INFO;
        } else if ("debug".equals(level)) {
            logLevel = LOG_LEVEL_DEBUG;
        } else if ("trace".equals(level)) {
            logLevel = LOG_LEVEL_TRACE;
        } else {
            logLevel = LOG_LEVEL_INFO;
        }
    }

    /**
     * {@inheritDoc}
     */
    public final boolean isTraceEnabled() {
        return logLevel <= LOG_LEVEL_TRACE;
    }

    /**
     * {@inheritDoc}
     */
    public final boolean isDebugEnabled() {
        return logLevel <= LOG_LEVEL_DEBUG;
    }

    /**
     * {@inheritDoc}
     */
    public final boolean isInfoEnabled() {
        return logLevel <= LOG_LEVEL_INFO;
    }

    /**
     * {@inheritDoc}
     */
    public final boolean isWarnEnabled() {
        return logLevel <= LOG_LEVEL_WARN;
    }

    /**
     * {@inheritDoc}
     */
    public final boolean isErrorEnabled() {
        return logLevel <= LOG_LEVEL_ERROR;
    }

    /**
     * {@inheritDoc}
     */
    public final boolean isFatalEnabled() {
        return logLevel <= LOG_LEVEL_FATAL;
    }

    /**
     * {@inheritDoc}
     */
    public final void trace(Object message) {
        if (isTraceEnabled()) {
            log(LOG_LEVEL_TRACE, message, null);
        }
    }

    /**
     * {@inheritDoc}
     */
    public final void trace(Object message, Throwable t) {
        if (isTraceEnabled()) {
            log(LOG_LEVEL_TRACE, message, t);
        }
    }

    /**
     * {@inheritDoc}
     */
    public final void debug(Object message) {
        if (isDebugEnabled()) {
            log(LOG_LEVEL_DEBUG, message, null);
        }
    }

    /**
     * {@inheritDoc}
     */
    public final void debug(Object message, Throwable t) {
        if (isDebugEnabled()) {
            log(LOG_LEVEL_DEBUG, message, t);
        }
    }

    /**
     * {@inheritDoc}
     */
    public final void info(Object message) {
        if (isInfoEnabled()) {
            log(LOG_LEVEL_INFO, message, null);
        }
    }

    /**
     * {@inheritDoc}
     */
    public final void info(Object message, Throwable t) {
        if (isInfoEnabled()) {
            log(LOG_LEVEL_INFO, message, t);
        }
    }

    /**
     * {@inheritDoc}
     */
    public final void warn(Object message) {
        if (isWarnEnabled()) {
            log(LOG_LEVEL_WARN, message, null);
        }
    }

    /**
     * {@inheritDoc}
     */
    public final void warn(Object message, Throwable t) {
        if (isWarnEnabled()) {
            log(LOG_LEVEL_WARN, message, t);
        }
    }

    /**
     * {@inheritDoc}
     */
    public final void error(Object message) {
        if (isErrorEnabled()) {
            log(LOG_LEVEL_ERROR, message, null);
        }
    }

    /**
     * {@inheritDoc}
     */
    public final void error(Object message, Throwable t) {
        if (isErrorEnabled()) {
            log(LOG_LEVEL_ERROR, message, t);
        }
    }

    /**
     * {@inheritDoc}
     */
    public final void fatal(Object message) {
        if (isFatalEnabled()) {
            log(LOG_LEVEL_FATAL, message, null);
        }
    }

    /**
     * {@inheritDoc}
     */
    public final void fatal(Object message, Throwable t) {
        if (isFatalEnabled()) {
            log(LOG_LEVEL_FATAL, message, t);
        }
    }

    /**
     * Do the actual logging.
     * This method assembles the message and prints it to
     * and then calls <code>write()</code> to cause it to be written.</p>
     *
     * @param type One of the LOG_LEVEL_XXX constants defining the log level
     * @param message The message itself (typically a String)
     * @param t The exception whose stack trace should be logged
     */
    protected void log(int type, Object message, Throwable t) {
        StringBuffer buf = new StringBuffer();
        // Append the message
        buf.append(String.valueOf(message));
        if (t != null) {
            buf.append("\n");
            // Append a stack trace or just the stack trace message.
            if (!isDebugEnabled()) {
                buf.append(t.toString());
                buf.append("\n");
            } else {
                java.io.StringWriter sw = new java.io.StringWriter(1024);
                java.io.PrintWriter pw = new java.io.PrintWriter(sw);
                t.printStackTrace(pw);
                pw.close();
                buf.append(sw.toString());
            }
        }

        // Print to the appropriate destination
        if (type >= LOG_LEVEL_WARN) {
            System.err.println(buf);
        } else {
            System.out.println(buf);
        }

    }
}
