/*
 * 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 org.apache.log4j;

import java.util.Enumeration;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.log4j.helpers.NullEnumeration;
import org.apache.log4j.legacy.core.CategoryUtil;
import org.apache.log4j.or.ObjectRenderer;
import org.apache.log4j.or.RendererSupport;
import org.apache.log4j.spi.LoggerFactory;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.logging.log4j.message.MapMessage;
import org.apache.logging.log4j.spi.ExtendedLogger;
import org.apache.logging.log4j.spi.LoggerContext;
import org.apache.logging.log4j.message.LocalizedMessage;
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.message.ObjectMessage;
import org.apache.logging.log4j.spi.AbstractLoggerAdapter;
import org.apache.logging.log4j.util.Strings;


/**
 * Implementation of the Category class for compatibility, despite it having been deprecated a long, long time ago.
 */
public class Category {

    private static final PrivateAdapter adapter = new PrivateAdapter();

    private static final Map<LoggerContext, ConcurrentMap<String, Logger>> CONTEXT_MAP =
        new WeakHashMap<>();

    private static final String FQCN = Category.class.getName();

    private static final boolean isCoreAvailable;

    private final Map<Class<?>, ObjectRenderer> rendererMap;

    static {
        boolean available;

        try {
            available = Class.forName("org.apache.logging.log4j.core.Logger") != null;
        } catch (Exception ex) {
            available = false;
        }
        isCoreAvailable = available;
    }

    /**
     * Resource bundle for localized messages.
     */
    protected ResourceBundle bundle = null;

    private final org.apache.logging.log4j.Logger logger;

    /**
     * Constructor used by Logger to specify a LoggerContext.
     * @param context The LoggerContext.
     * @param name The name of the Logger.
     */
    protected Category(final LoggerContext context, final String name) {
        this.logger = context.getLogger(name);
        rendererMap = ((RendererSupport) LogManager.getLoggerRepository()).getRendererMap();
    }

    /**
     * Constructor exposed by Log4j 1.2.
     * @param name The name of the Logger.
     */
    protected Category(final String name) {
        this(PrivateManager.getContext(), name);
    }

    private Category(final org.apache.logging.log4j.Logger logger) {
        this.logger = logger;
        rendererMap = ((RendererSupport) LogManager.getLoggerRepository()).getRendererMap();
    }

    public static Category getInstance(final String name) {
        return getInstance(PrivateManager.getContext(), name, adapter);
    }

    static Logger getInstance(final LoggerContext context, final String name) {
        return getInstance(context, name, adapter);
    }

    static Logger getInstance(final LoggerContext context, final String name, final LoggerFactory factory) {
        final ConcurrentMap<String, Logger> loggers = getLoggersMap(context);
        Logger logger = loggers.get(name);
        if (logger != null) {
            return logger;
        }
        logger = factory.makeNewLoggerInstance(name);
        final Logger prev = loggers.putIfAbsent(name, logger);
        return prev == null ? logger : prev;
    }

    static Logger getInstance(final LoggerContext context, final String name, final PrivateAdapter factory) {
        final ConcurrentMap<String, Logger> loggers = getLoggersMap(context);
        Logger logger = loggers.get(name);
        if (logger != null) {
            return logger;
        }
        logger = factory.newLogger(name, context);
        final Logger prev = loggers.putIfAbsent(name, logger);
        return prev == null ? logger : prev;
    }

    public static Category getInstance(@SuppressWarnings("rawtypes") final Class clazz) {
        return getInstance(clazz.getName());
    }

    static Logger getInstance(final LoggerContext context, @SuppressWarnings("rawtypes") final Class clazz) {
        return getInstance(context, clazz.getName());
    }

    public final String getName() {
        return logger.getName();
    }

    org.apache.logging.log4j.Logger getLogger() {
        return logger;
    }

    public final Category getParent() {
        if (!isCoreAvailable) {
            return null;
        }
        org.apache.logging.log4j.Logger parent = CategoryUtil.getParent(logger);
        LoggerContext loggerContext = CategoryUtil.getLoggerContext(logger);
        if (parent == null || loggerContext == null) {
            return null;
        }
        final ConcurrentMap<String, Logger> loggers = getLoggersMap(loggerContext);
        final Logger l = loggers.get(parent.getName());
        return l == null ? new Category(parent) : l;
    }

    public static Category getRoot() {
        return getInstance(Strings.EMPTY);
    }

    static Logger getRoot(final LoggerContext context) {
        return getInstance(context, Strings.EMPTY);
    }

    private static ConcurrentMap<String, Logger> getLoggersMap(final LoggerContext context) {
        synchronized (CONTEXT_MAP) {
            ConcurrentMap<String, Logger> map = CONTEXT_MAP.get(context);
            if (map == null) {
                map = new ConcurrentHashMap<>();
                CONTEXT_MAP.put(context, map);
            }
            return map;
        }
    }

    /**
     Returns all the currently defined categories in the default
     hierarchy as an {@link java.util.Enumeration Enumeration}.

     <p>The root category is <em>not</em> included in the returned
     {@link Enumeration}.
     @return and Enumeration of the Categories.

     @deprecated Please use {@link LogManager#getCurrentLoggers()} instead.
     */
    @SuppressWarnings("rawtypes")
    @Deprecated
    public static Enumeration getCurrentCategories() {
        return LogManager.getCurrentLoggers();
    }

    public final Level getEffectiveLevel() {
        switch (logger.getLevel().getStandardLevel()) {
        case ALL:
            return Level.ALL;
        case TRACE:
            return Level.TRACE;
        case DEBUG:
            return Level.DEBUG;
        case INFO:
            return Level.INFO;
        case WARN:
            return Level.WARN;
        case ERROR:
            return Level.ERROR;
        case FATAL:
            return Level.FATAL;
        default:
            // TODO Should this be an IllegalStateException?
            return Level.OFF;
        }
    }

    public final Priority getChainedPriority() {
        return getEffectiveLevel();
    }

    public final Level getLevel() {
        return getEffectiveLevel();
    }

    public void setLevel(final Level level) {
        setLevel(level.levelStr);
    }

    public final Level getPriority() {
        return getEffectiveLevel();
    }

    public void setPriority(final Priority priority) {
        setLevel(priority.levelStr);
    }

    private void setLevel(final String levelStr) {
        if (isCoreAvailable) {
            CategoryUtil.setLevel(logger, org.apache.logging.log4j.Level.toLevel(levelStr));
        }
    }

    public void debug(final Object message) {
        maybeLog(FQCN, org.apache.logging.log4j.Level.DEBUG, message, null);
    }

    public void debug(final Object message, final Throwable t) {
        maybeLog(FQCN, org.apache.logging.log4j.Level.DEBUG, message, t);
    }

    public boolean isDebugEnabled() {
        return logger.isDebugEnabled();
    }

    public void error(final Object message) {
        maybeLog(FQCN, org.apache.logging.log4j.Level.ERROR, message, null);
    }

    public void error(final Object message, final Throwable t) {
        maybeLog(FQCN, org.apache.logging.log4j.Level.ERROR, message, t);
    }

    public boolean isErrorEnabled() {
        return logger.isErrorEnabled();
    }

    public void warn(final Object message) {
        maybeLog(FQCN, org.apache.logging.log4j.Level.WARN, message, null);
    }

    public void warn(final Object message, final Throwable t) {
        maybeLog(FQCN, org.apache.logging.log4j.Level.WARN, message, t);
    }

    public boolean isWarnEnabled() {
        return logger.isWarnEnabled();
    }

    public void fatal(final Object message) {
        maybeLog(FQCN, org.apache.logging.log4j.Level.FATAL, message, null);
    }

    public void fatal(final Object message, final Throwable t) {
        maybeLog(FQCN, org.apache.logging.log4j.Level.FATAL, message, t);
    }

    public boolean isFatalEnabled() {
        return logger.isFatalEnabled();
    }

    public void info(final Object message) {
        maybeLog(FQCN, org.apache.logging.log4j.Level.INFO, message, null);
    }

    public void info(final Object message, final Throwable t) {
        maybeLog(FQCN, org.apache.logging.log4j.Level.INFO, message, t);
    }

    public boolean isInfoEnabled() {
        return logger.isInfoEnabled();
    }

    public void trace(final Object message) {
        maybeLog(FQCN, org.apache.logging.log4j.Level.TRACE, message, null);
    }

    public void trace(final Object message, final Throwable t) {
        maybeLog(FQCN, org.apache.logging.log4j.Level.TRACE, message, t);
    }

    public boolean isTraceEnabled() {
        return logger.isTraceEnabled();
    }

    public boolean isEnabledFor(final Priority level) {
        final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString());
        return isEnabledFor(lvl);
    }

    /**
     * No-op implementation.
     * @param appender The Appender to add.
     */
    public void addAppender(final Appender appender) {
    }

    /**
     * No-op implementation.
     * @param event The logging event.
     */
    public void callAppenders(final LoggingEvent event) {
    }

    @SuppressWarnings("rawtypes")
    public Enumeration getAllAppenders() {
        return NullEnumeration.getInstance();
    }

    /**
     * No-op implementation.
     * @param name The name of the Appender.
     * @return null.
     */
    public Appender getAppender(final String name) {
        return null;
    }

    /**
     Is the appender passed as parameter attached to this category?
     * @param appender The Appender to add.
     * @return true if the appender is attached.
     */
    public boolean isAttached(final Appender appender) {
        return false;
    }

    /**
     * No-op implementation.
     */
    public void removeAllAppenders() {
    }

    /**
     * No-op implementation.
     * @param appender The Appender to remove.
     */
    public void removeAppender(final Appender appender) {
    }

    /**
     * No-op implementation.
     * @param name The Appender to remove.
     */
    public void removeAppender(final String name) {
    }

    /**
     * No-op implementation.
     */
    public static void shutdown() {
    }

    public void forcedLog(final String fqcn, final Priority level, final Object message, final Throwable t) {
        final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString());
        if (logger instanceof ExtendedLogger) {
            @SuppressWarnings("unchecked")
            Message msg = message instanceof Message ? (Message) message : message instanceof Map ?
                    new MapMessage((Map) message) : new ObjectMessage(message);
            ((ExtendedLogger) logger).logMessage(fqcn, lvl, null, msg, t);
        } else {
            ObjectRenderer renderer = get(message.getClass());
            final Message msg = message instanceof Message ? (Message) message : renderer != null ?
                    new RenderedMessage(renderer, message) : new ObjectMessage(message);
            logger.log(lvl, msg, t);
        }
    }

    public boolean exists(final String name) {
        return PrivateManager.getContext().hasLogger(name);
    }

    public boolean getAdditivity() {
        return isCoreAvailable ? CategoryUtil.isAdditive(logger) : false;
    }

    public void setAdditivity(final boolean additivity) {
        if (isCoreAvailable) {
            CategoryUtil.setAdditivity(logger, additivity);
        }
    }

    public void setResourceBundle(final ResourceBundle bundle) {
        this.bundle = bundle;
    }

    public ResourceBundle getResourceBundle() {
        if (bundle != null) {
            return bundle;
        }
        String name = logger.getName();
        if (isCoreAvailable) {
            LoggerContext ctx = CategoryUtil.getLoggerContext(logger);
            if (ctx != null) {
                final ConcurrentMap<String, Logger> loggers = getLoggersMap(ctx);
                while ((name = getSubName(name)) != null) {
                    final Logger subLogger = loggers.get(name);
                    if (subLogger != null) {
                        final ResourceBundle rb = subLogger.bundle;
                        if (rb != null) {
                            return rb;
                        }
                    }
                }
            }
        }
        return null;
    }

    private static  String getSubName(final String name) {
        if (Strings.isEmpty(name)) {
            return null;
        }
        final int i = name.lastIndexOf('.');
        return i > 0 ? name.substring(0, i) : Strings.EMPTY;
    }

    /**
     If <code>assertion</code> parameter is {@code false}, then
     logs <code>msg</code> as an {@link #error(Object) error} statement.

     <p>The <code>assert</code> method has been renamed to
     <code>assertLog</code> because <code>assert</code> is a language
     reserved word in JDK 1.4.

     @param assertion The assertion.
     @param msg The message to print if <code>assertion</code> is
     false.

     @since 1.2
     */
    public void assertLog(final boolean assertion, final String msg) {
        if (!assertion) {
            this.error(msg);
        }
    }

    public void l7dlog(final Priority priority, final String key, final Throwable t) {
        if (isEnabledFor(priority)) {
            final Message msg = new LocalizedMessage(bundle, key, null);
            forcedLog(FQCN, priority, msg, t);
        }
    }

    public void l7dlog(final Priority priority, final String key, final Object[] params, final Throwable t) {
        if (isEnabledFor(priority)) {
            final Message msg = new LocalizedMessage(bundle, key, params);
            forcedLog(FQCN, priority, msg, t);
        }
    }

    public void log(final Priority priority, final Object message, final Throwable t) {
        if (isEnabledFor(priority)) {
            @SuppressWarnings("unchecked")
            final Message msg = message instanceof Map ? new MapMessage((Map) message) : new ObjectMessage(message);
            forcedLog(FQCN, priority, msg, t);
        }
    }

    public void log(final Priority priority, final Object message) {
        if (isEnabledFor(priority)) {
            @SuppressWarnings("unchecked")
            final Message msg = message instanceof Map ? new MapMessage((Map) message) : new ObjectMessage(message);
            forcedLog(FQCN, priority, msg, null);
        }
    }

    public void log(final String fqcn, final Priority priority, final Object message, final Throwable t) {
        if (isEnabledFor(priority)) {
            final Message msg = new ObjectMessage(message);
            forcedLog(fqcn, priority, msg, t);
        }
    }

    private void maybeLog(final String fqcn, final org.apache.logging.log4j.Level level,
            final Object message, final Throwable throwable) {
        if (logger.isEnabled(level)) {
            @SuppressWarnings("unchecked")
            Message msg = message instanceof Map ? new MapMessage((Map) message) : new ObjectMessage(message);
            if (logger instanceof ExtendedLogger) {
                ((ExtendedLogger) logger).logMessage(fqcn, level, null, msg, throwable);
            } else {
                logger.log(level, msg, throwable);
            }
        }
    }

    private static class PrivateAdapter extends AbstractLoggerAdapter<Logger> {

        @Override
        protected Logger newLogger(final String name, final org.apache.logging.log4j.spi.LoggerContext context) {
            return new Logger(context, name);
        }

        @Override
        protected org.apache.logging.log4j.spi.LoggerContext getContext() {
            return PrivateManager.getContext();
        }
    }

    /**
     * Private LogManager.
     */
    private static class PrivateManager extends org.apache.logging.log4j.LogManager {
        private static final String FQCN = Category.class.getName();

        public static LoggerContext getContext() {
            return getContext(FQCN, false);
        }

        public static org.apache.logging.log4j.Logger getLogger(final String name) {
            return getLogger(FQCN, name);
        }
    }

    private boolean isEnabledFor(final org.apache.logging.log4j.Level level) {
        return logger.isEnabled(level);
    }

    private ObjectRenderer get(Class clazz) {
        ObjectRenderer renderer = null;
        for(Class c = clazz; c != null; c = c.getSuperclass()) {
            renderer = rendererMap.get(c);
            if (renderer != null) {
                return renderer;
            }
            renderer = searchInterfaces(c);
            if (renderer != null) {
                return renderer;
            }
        }
        return null;
    }

    ObjectRenderer searchInterfaces(Class c) {
        ObjectRenderer renderer = rendererMap.get(c);
        if(renderer != null) {
            return renderer;
        } else {
            Class[] ia = c.getInterfaces();
            for (Class clazz : ia) {
                renderer = searchInterfaces(clazz);
                if (renderer != null) {
                    return renderer;
                }
            }
        }
        return null;
    }

}
