/*
 * 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.
 */

package freemarker.log;

import java.security.AccessControlException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;

/**
 * Delegates logger creation to an actual logging library. By default it looks for logger libraries in this order (in
 * FreeMarker 2.3.x): Log4J, Avalon LogKit, JUL (i.e., {@code java.util.logging}). Prior to FreeMarker 2.4, SLF4J and
 * Apache Commons Logging aren't searched automatically due to backward compatibility constraints. But if you have
 * {@code log4j-over-slf4j} properly installed (means, you have no real Log4j in your class path, and SLF4J has a
 * backing implementation like {@code logback-classic}), then FreeMarker will use SLF4J directly instead of Log4j (since
 * FreeMarker 2.3.22).
 * 
 * <p>
 * If the auto detection sequence describet above doesn't give you the result that you want, see
 * {@link #SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY}.
 */
public abstract class Logger {

    /**
     * The {@value #SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY} system property is used to select a logger library explicitly,
     * rather than relying on automatic selection. You meant to set this system property where the JVM is started, like
     * {@code java ... -Dorg.freemarker.loggerLibrary=SLF4j}. Setting it from Java code isn't reliable, also it can
     * cause confusion if you override the value set by others with {@code -D}.
     * 
     * <p>
     * If the requested logging library is not available, an error will be printed to the stderr, then logging will be
     * disabled.
     * 
     * <p>
     * The supported values are:
     * <ul>
     * <li>{@value #LIBRARY_NAME_SLF4J}: Use SLF4J (recommended)</li>
     * <li>{@value #LIBRARY_NAME_COMMONS_LOGGING}: Use Apache Commons Logging.</li>
     * <li>{@value #LIBRARY_NAME_LOG4J}: Use Log4j.</li>
     * <li>{@value #LIBRARY_NAME_JUL}: Use {@code java.util.logging}.</li>
     * <li>{@value #LIBRARY_NAME_AVALON}: Use Avalon LogKit (deprecated)</li>
     * <li>{@value #LIBRARY_NAME_AUTO}: Use automatic selection (default behavior). See {@link Logger} class
     * documentation for more.</li>
     * <li>{@value #LIBRARY_NAME_NONE}: Don't log.</li>
     * </ul>
     * 
     * @since 2.3.22
     */
    public static final String SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY = "org.freemarker.loggerLibrary";

    /**
     * Enum value used for {@link #selectLoggerLibrary(int)}; indicates auto-selection as described in the class
     * documentation of {@link #Logger()}.
     */
    public static final int LIBRARY_AUTO = -1;
    private static final int MIN_LIBRARY_ENUM = LIBRARY_AUTO;

    /**
     * {@value #SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY} property value; indicates auto-selection as described in the class
     * documentation of {@link #Logger()}. @since 2.3.22
     */
    public static final String LIBRARY_NAME_AUTO = "auto";

    /**
     * Enum value used for {@link #selectLoggerLibrary(int)}; indicates that no logging should occur.
     */
    public static final int LIBRARY_NONE = 0;

    /**
     * {@value #SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY} property value; indicates that no logging should occur. @since
     * 2.3.22
     */
    public static final String LIBRARY_NAME_NONE = "none";

    /**
     * Enum value used for {@link #selectLoggerLibrary(int)}; indicates that {@code java.util.logging} should be used.
     */
    public static final int LIBRARY_JAVA = 1;

    /**
     * {@value #SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY} property value; indicates that {@code java.util.logging} should be
     * used. @since 2.3.22
     */
    public static final String LIBRARY_NAME_JUL = "JUL";

    /**
     * Enum value used for {@link #selectLoggerLibrary(int)}; indicates that Avalon LogKit should be used.
     * 
     * @deprecated Avalon LogKit support will be removed sometimes in the future.
     */
    @Deprecated
    public static final int LIBRARY_AVALON = 2;

    /**
     * {@value #SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY} property value; indicates that Avalon LogKit should be used. @since
     * 2.3.22
     * 
     * @deprecated Avalon LogKit support will be removed sometimes in the future.
     */
    // This value is also used as part of the factory class name.
    @Deprecated
    public static final String LIBRARY_NAME_AVALON = "Avalon";

    /**
     * Enum value used for {@link #selectLoggerLibrary(int)}; indicates that Log4J should be used.
     */
    public static final int LIBRARY_LOG4J = 3;

    /**
     * {@value #SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY} property value; indicates that Log4J should be used. @since 2.3.22
     */
    // This value is also used as part of the factory class name.
    public static final String LIBRARY_NAME_LOG4J = "Log4j";

    /**
     * Enum value used for {@link #selectLoggerLibrary(int)}; indicates that Apache commons-logging should be used.
     */
    public static final int LIBRARY_COMMONS = 4;

    /**
     * {@value #SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY} property value; indicates that Apache commons-logging should be
     * used. @since 2.3.22
     */
    // This value is also used as part of the factory class name.
    public static final String LIBRARY_NAME_COMMONS_LOGGING = "CommonsLogging";

    /**
     * Constant used with {@link #selectLoggerLibrary(int)}; indicates that SLF4J should be used.
     */
    public static final int LIBRARY_SLF4J = 5;

    /**
     * {@value #SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY} property value; indicates that SLF4J should be used. @since 2.3.22
     */
    // This value is also used as part of the factory class name.
    public static final String LIBRARY_NAME_SLF4J = "SLF4J";
    private static final int MAX_LIBRARY_ENUM = LIBRARY_SLF4J;

    private static final String REAL_LOG4J_PRESENCE_CLASS = "org.apache.log4j.FileAppender";
    private static final String LOG4J_OVER_SLF4J_TESTER_CLASS = "freemarker.log._Log4jOverSLF4JTester";

    /**
     * Order matters! Starts with the lowest priority.
     */
    private static final String[] LIBRARIES_BY_PRIORITY = {
            null, LIBRARY_NAME_JUL,
            "org.apache.log.Logger", LIBRARY_NAME_AVALON,
            "org.apache.log4j.Logger", LIBRARY_NAME_LOG4J,
            /* In 2.3.x this two is skipped by LIBRARY_AUTO: */
            "org.apache.commons.logging.Log", LIBRARY_NAME_COMMONS_LOGGING,
            "org.slf4j.Logger", LIBRARY_NAME_SLF4J,
    };

    private static String getAvailabilityCheckClassName(int libraryEnum) {
        if (libraryEnum == LIBRARY_AUTO || libraryEnum == LIBRARY_NONE) {
            // Statically linked
            return null;
        }
        return LIBRARIES_BY_PRIORITY[(libraryEnum - 1) * 2];
    }

    static {
        if (LIBRARIES_BY_PRIORITY.length / 2 != MAX_LIBRARY_ENUM) {
            throw new AssertionError();
        }
    }

    private static String getLibraryName(int libraryEnum) {
        if (libraryEnum == LIBRARY_AUTO) {
            return LIBRARY_NAME_AUTO;
        }
        if (libraryEnum == LIBRARY_NONE) {
            return LIBRARY_NAME_NONE;
        }
        return LIBRARIES_BY_PRIORITY[(libraryEnum - 1) * 2 + 1];
    }

    private static boolean isAutoDetected(int libraryEnum) {
        // 2.4: Remove libraryEnum == LIBRARY_SLF4J || libraryEnum == LIBRARY_COMMONS
        return !(libraryEnum == LIBRARY_AUTO || libraryEnum == LIBRARY_NONE
                || libraryEnum == LIBRARY_SLF4J || libraryEnum == LIBRARY_COMMONS);
    }

    private static int libraryEnum;
    private static LoggerFactory loggerFactory;
    private static boolean initializedFromSystemProperty;

    private static String categoryPrefix = "";

    private static final Map loggersByCategory = new HashMap();

    /**
     * Selects the logger library to use, unless it's already specified by the
     * {@value #SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY} system property. Call this early in application initialization
     * phase, before calling any other FreeMarker API-s, since once parts of the FreeMarker library bind to the logging
     * subsystem, the change in this value will have no effect on them.
     * 
     * @param libraryEnum
     *            One of {@code LIBRARY_...} constants. By default, {@link #LIBRARY_AUTO} is used.
     * 
     * @throws ClassNotFoundException
     *             if an explicit logging library is asked for (that is, not {@value #LIBRARY_AUTO} or
     *             {@value #LIBRARY_NONE}) and it's not found in the classpath.
     * 
     * @deprecated This method isn't reliable, unless you can somehow ensure that you access the FreeMarker classes
     *             first; use the {@value #SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY} Java system property instead, like
     *             {@code java ... -Dorg.freemarker.loggerLibrary=slf4j}. See
     *             {@link #SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY} for more.
     */
    @Deprecated
    public static void selectLoggerLibrary(int libraryEnum) throws ClassNotFoundException {
        if (libraryEnum < MIN_LIBRARY_ENUM || libraryEnum > MAX_LIBRARY_ENUM) {
            throw new IllegalArgumentException("Library enum value out of range");
        }

        synchronized (Logger.class) {
            final boolean loggerFactoryWasAlreadySet = loggerFactory != null;
            if (!loggerFactoryWasAlreadySet || libraryEnum != Logger.libraryEnum) {
                // Creates the factory only if it can be done based on system property:
                ensureLoggerFactorySet(true);

                // The system property has precedence because this method was deprecated by it:
                if (!initializedFromSystemProperty || loggerFactory == null) {
                    int replacedLibraryEnum = Logger.libraryEnum;
                    setLibrary(libraryEnum);
                    loggersByCategory.clear();
                    if (loggerFactoryWasAlreadySet) {
                        logWarnInLogger("Logger library was already set earlier to \""
                                + getLibraryName(replacedLibraryEnum) + "\"; "
                                + "change to \"" + getLibraryName(libraryEnum) + "\" won't effect loggers created "
                                + "earlier.");
                    }
                } else if (libraryEnum != Logger.libraryEnum) {
                    logWarnInLogger("Ignored " + Logger.class.getName() + ".selectLoggerLibrary(\""
                            + getLibraryName(libraryEnum)
                            + "\") call, because the \"" + SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY
                            + "\" system property is set to \"" + getLibraryName(Logger.libraryEnum) + "\".");
                }
            }
        }
    }

    /**
     * Sets a category prefix. This prefix is prepended to any logger category name. This makes it possible to have
     * different FreeMarker logger categories on a per-application basis (better said, per-classloader basis). By
     * default the category prefix is the empty string. If you set a non-empty category prefix, be sure to include the
     * trailing separator dot (i.e. "MyApp.") If you want to change the default setting, do it early in application
     * initialization phase, before calling any other FreeMarker API since once various parts of the FreeMarker library
     * bind to the logging subsystem, the change in this value will have no effect on them.
     * 
     * @deprecated This wasn't reliable, unless you can somehow ensure that you access the FreeMarker classes first. As
     *             it's not known to be useful for users, consider it removed.
     */
    @Deprecated
    public static void setCategoryPrefix(String prefix) {
        synchronized (Logger.class) {
            if (prefix == null) {
                throw new IllegalArgumentException();
            }
            categoryPrefix = prefix;
        }
    }

    /**
     * Logs a debugging message.
     */
    public abstract void debug(String message);

    /**
     * Logs a debugging message with accompanying throwable.
     */
    public abstract void debug(String message, Throwable t);

    /**
     * Logs an informational message.
     */
    public abstract void info(String message);

    /**
     * Logs an informational message with accompanying throwable.
     */
    public abstract void info(String message, Throwable t);

    /**
     * Logs a warning message.
     */
    public abstract void warn(String message);

    /**
     * Logs a warning message with accompanying throwable.
     */
    public abstract void warn(String message, Throwable t);

    /**
     * Logs an error message.
     */
    public abstract void error(String message);

    /**
     * Logs an error message with accompanying throwable.
     */
    public abstract void error(String message, Throwable t);

    /**
     * Returns true if this logger will log debug messages.
     */
    public abstract boolean isDebugEnabled();

    /**
     * Returns true if this logger will log informational messages.
     */
    public abstract boolean isInfoEnabled();

    /**
     * Returns true if this logger will log warning messages.
     */
    public abstract boolean isWarnEnabled();

    /**
     * Returns true if this logger will log error messages.
     */
    public abstract boolean isErrorEnabled();

    /**
     * Returns true if this logger will log fatal error messages.
     */
    public abstract boolean isFatalEnabled();

    /**
     * Returns a logger for the specified category.
     * 
     * @param category
     *            a dot separated hierarchical category name. If a category prefix is in effect, it's prepended to the
     *            category name.
     */
    public static Logger getLogger(String category) {
        if (categoryPrefix.length() != 0) {
            category = categoryPrefix + category;
        }
        synchronized (loggersByCategory) {
            Logger logger = (Logger) loggersByCategory.get(category);
            if (logger == null) {
                ensureLoggerFactorySet(false);
                logger = loggerFactory.getLogger(category);
                loggersByCategory.put(category, logger);
            }
            return logger;
        }
    }

    private static void ensureLoggerFactorySet(boolean onlyIfCanBeSetFromSysProp) {
        if (loggerFactory != null) return;
        synchronized (Logger.class) {
            if (loggerFactory != null) return;

            String sysPropVal = getSystemProperty(SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY);

            final int libraryEnum;
            if (sysPropVal != null) {
                sysPropVal = sysPropVal.trim();

                boolean foundMatch = false;
                int matchedEnum = MIN_LIBRARY_ENUM;
                do {
                    if (sysPropVal.equalsIgnoreCase(getLibraryName(matchedEnum))) {
                        foundMatch = true;
                    } else {
                        matchedEnum++;
                    }
                } while (matchedEnum <= MAX_LIBRARY_ENUM && !foundMatch);

                if (!foundMatch) {
                    logWarnInLogger("Ignored invalid \"" + SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY
                            + "\" system property value: \"" + sysPropVal + "\"");
                    if (onlyIfCanBeSetFromSysProp) return;
                }

                libraryEnum = foundMatch ? matchedEnum : LIBRARY_AUTO;
            } else {
                if (onlyIfCanBeSetFromSysProp) return;
                libraryEnum = LIBRARY_AUTO;
            }

            try {
                setLibrary(libraryEnum);
                if (sysPropVal != null) {
                    initializedFromSystemProperty = true;
                }
            } catch (Throwable e) {
                final boolean disableLogging = !(onlyIfCanBeSetFromSysProp && sysPropVal != null);
                logErrorInLogger(
                        "Couldn't set up logger for \"" + getLibraryName(libraryEnum) + "\""
                                + (disableLogging ? "; logging disabled" : "."), e);
                if (disableLogging) {
                    try {
                        setLibrary(LIBRARY_NONE);
                    } catch (ClassNotFoundException e2) {
                        throw new RuntimeException("Bug", e2);
                    }
                }
            }
        }
    }

    /**
     * @throws ClassNotFoundException
     *             If the requested logger library is not available. Never thrown for {@link #LIBRARY_AUTO}.
     */
    private static LoggerFactory createLoggerFactory(int libraryEnum) throws ClassNotFoundException {
        if (libraryEnum == LIBRARY_AUTO) {
            for (int libraryEnumToTry = MAX_LIBRARY_ENUM; libraryEnumToTry >= MIN_LIBRARY_ENUM; libraryEnumToTry--) {
                if (!isAutoDetected(libraryEnumToTry)) continue;
                if (libraryEnumToTry == LIBRARY_LOG4J && hasLog4LibraryThatDelegatesToWorkingSLF4J()) {
                    libraryEnumToTry = LIBRARY_SLF4J;
                }

                try {
                    return createLoggerFactoryForNonAuto(libraryEnumToTry);
                } catch (ClassNotFoundException e) {
                    // Expected, intentionally suppressed.
                } catch (Throwable e) {
                    logErrorInLogger(
                            "Unexpected error when initializing logging for \""
                                    + getLibraryName(libraryEnumToTry) + "\".",
                            e);
                }
            }
            logWarnInLogger("Auto detecton couldn't set up any logger libraries; FreeMarker logging suppressed.");
            return new _NullLoggerFactory();
        } else {
            return createLoggerFactoryForNonAuto(libraryEnum);
        }
    }

    /**
     * @throws ClassNotFoundException
     *             If the required logger library is not available.
     */
    private static LoggerFactory createLoggerFactoryForNonAuto(int libraryEnum) throws ClassNotFoundException {
        final String availabilityCheckClassName = getAvailabilityCheckClassName(libraryEnum);
        if (availabilityCheckClassName != null) { // Dynamically created factory
            Class.forName(availabilityCheckClassName);
            String libraryName = getLibraryName(libraryEnum);
            try {
                return (LoggerFactory) Class.forName(
                        "freemarker.log._" + libraryName + "LoggerFactory").newInstance();
            } catch (Exception e) {
                throw new RuntimeException(
                        "Unexpected error when creating logger factory for \"" + libraryName + "\".", e);
            }
        } else { // Non-dynamically created factory
            if (libraryEnum == LIBRARY_JAVA) {
                return new _JULLoggerFactory();
            } else if (libraryEnum == LIBRARY_NONE) {
                return new _NullLoggerFactory();
            } else {
                throw new RuntimeException("Bug");
            }
        }
    }

    private static boolean hasLog4LibraryThatDelegatesToWorkingSLF4J() {
        try {
            Class.forName(getAvailabilityCheckClassName(LIBRARY_LOG4J));
            Class.forName(getAvailabilityCheckClassName(LIBRARY_SLF4J));
        } catch (Throwable e) {
            return false;
        }
        try {
            Class.forName(REAL_LOG4J_PRESENCE_CLASS);
            return false;
        } catch (ClassNotFoundException e) {
            try {
                Object r = Class.forName(LOG4J_OVER_SLF4J_TESTER_CLASS)
                        .getMethod("test", new Class[] {}).invoke(null);
                return ((Boolean) r).booleanValue();
            } catch (Throwable e2) {
                return false;
            }
        }
    }

    private synchronized static void setLibrary(int libraryEnum) throws ClassNotFoundException {
        loggerFactory = createLoggerFactory(libraryEnum);
        Logger.libraryEnum = libraryEnum;
    }

    private static void logWarnInLogger(String message) {
        logInLogger(false, message, null);
    }

    private static void logErrorInLogger(String message, Throwable exception) {
        logInLogger(true, message, exception);
    }

    private static void logInLogger(boolean error, String message, Throwable exception) {
        boolean canUseRealLogger;
        synchronized (Logger.class) {
            canUseRealLogger = loggerFactory != null && !(loggerFactory instanceof _NullLoggerFactory);
        }

        if (canUseRealLogger) {
            try {
                final Logger logger = Logger.getLogger("freemarker.logger");
                if (error) {
                    logger.error(message);
                } else {
                    logger.warn(message);
                }
            } catch (Throwable e) {
                canUseRealLogger = false;
            }
        }

        if (!canUseRealLogger) {
            System.err.println((error ? "ERROR" : "WARN") + " "
                    + LoggerFactory.class.getName() + ": " + message);
            if (exception != null) {
                System.err.println("\tException: " + tryToString(exception));
                while (exception.getCause() != null) {
                    exception = exception.getCause();
                    System.err.println("\tCaused by: " + tryToString(exception));
                }
            }
        }
    }

    /**
     * Don't use {@link freemarker.template.utility.SecurityUtilities#getSystemProperty(String, String)} here, as it
     * (might) depends on the logger, hence interfering with the initialization.
     */
    private static String getSystemProperty(final String key) {
        try {
            return (String) AccessController.doPrivileged(
                    new PrivilegedAction() {
                        @Override
                        public Object run() {
                            return System.getProperty(key, null);
                        }
                    });
        } catch (AccessControlException e) {
            logWarnInLogger("Insufficient permissions to read system property \"" + key + "\".");
            return null;
        } catch (Throwable e) {
            logErrorInLogger("Failed to read system property \"" + key + "\".", e);
            return null;
        }
    }

    /**
     * Don't use {@link freemarker.template.utility.StringUtil#tryToString(Object)} here, as it might depends on the
     * logger, hence interfering with the initialization.
     */
    private static String tryToString(Object object) {
        if (object == null) return null;
        try {
            return object.toString();
        } catch (Throwable e) {
            return object.getClass().getName();
        }
    }

}
