/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.logging;


import java.io.OutputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.StreamHandler;

import org.eclipse.persistence.sessions.Session;

/**
 * PUBLIC:
 * <p>
 * This is a wrapper class for java.util.logging.  It is used when messages need to
 * be logged through java.util.logging.
 * </p>
 *  @see SessionLog
 *  @see AbstractSessionLog
 *  @see SessionLogEntry
 *  @see Session
 */
public class JavaLog extends AbstractSessionLog {

    /**
     * Stores the default session name in case there is the session name is missing.
     */
    public static final String TOPLINK_NAMESPACE = "org.eclipse.persistence";
    protected static final String LOGGING_LOCALIZATION_STRING = "org.eclipse.persistence.internal.localization.i18n.LoggingLocalizationResource";
    protected static final String TRACE_LOCALIZATION_STRING = "org.eclipse.persistence.internal.localization.i18n.TraceLocalizationResource";
    public static final String DEFAULT_TOPLINK_NAMESPACE = TOPLINK_NAMESPACE + ".default";
    public static final String SESSION_TOPLINK_NAMESPACE = TOPLINK_NAMESPACE + ".session";

    /**
     * Stores all the java.util.logging.Levels.  The indexes are TopLink logging levels.
     */
    private static final Level[] levels = new Level[] { Level.ALL, Level.FINEST, Level.FINER, Level.FINE, Level.CONFIG, Level.INFO, Level.WARNING, Level.SEVERE, Level.OFF };

    /**
     * Represents the HashMap that stores all the name space strings.
     * The keys are category names.  The values are namespace strings.
     */
    private Map nameSpaceMap  = new HashMap();

    /**
     * Stores the namespace for session, i.e."{@code org.eclipse.persistence.session.<sessionname>}".
     */
    private String sessionNameSpace;

    /**
     * Stores the Logger for session namespace, i.e. "{@code org.eclipse.persistence.session.<sessionname>}".
     */
    private Logger sessionLogger;

    private Map categoryloggers = new HashMap<String, Logger>();

    /**
     * INTERNAL:
     */

    public JavaLog(){
        super();
        addLogger(DEFAULT_TOPLINK_NAMESPACE, DEFAULT_TOPLINK_NAMESPACE);
    }

    /**
     * INTERNAL:
     * Add Logger to the categoryloggers.
     */
    protected void addLogger(String loggerCategory, String loggerNameSpace) {
        categoryloggers.put(loggerCategory, Logger.getLogger(loggerNameSpace));
    }

    /**
     * INTERNAL:
     * Return catagoryloggers
     */
     public Map getCategoryLoggers() {
         return categoryloggers;
     }

    /**
     * PUBLIC:
     * <p>
     * Return the effective log level for the name space extracted from session and category.
     * If a Logger's level is set to be null then the Logger will use an effective Level that will
     * be obtained by walking up the parent tree and using the first non-null Level.
     * </p>
     *
     * @return the effective log level.
     */
    @Override
    public int getLevel(String category) {
        Logger logger = getLogger(category);
        while ((logger != null) && (logger.getLevel() == null)) {
            logger = logger.getParent();
        }

        if (logger == null) {
            return OFF;
        }

        //For a given java.util.logging.Level, return the index (ie, TopLink logging level)
        int logLevel = logger.getLevel().intValue();
        for (int i = 0; i < levels.length ; i++) {
            if (logLevel == levels[i].intValue()) {
                return i;
            }
        }
        return OFF;
    }

    /**
     * PUBLIC:
     * <p>
     * Set the log level to a logger with name space extracted from the given category.
     * </p>
     */
    @Override
    public void setLevel(final int level, String category) {
        final Logger logger = getLogger(category);
        if (logger == null) {
            return;
        }

        AccessController.doPrivileged(new PrivilegedAction() {
            @Override
            public Object run() {
                logger.setLevel(getJavaLevel(level));
                return null; // nothing to return
            }
        });
    }

    /**
     * PUBLIC:
     * <p>
     * Set the output stream  that will receive the formatted log entries.
     * </p>
     *
     * @param fileOutputStream the file output stream will receive the formatted log entries.
     */
    @Override
    public void setWriter(OutputStream fileOutputStream){
        StreamHandler sh = new StreamHandler(fileOutputStream,new LogFormatter());
        ((Logger)categoryloggers.get(DEFAULT_TOPLINK_NAMESPACE)).addHandler(sh);
        if(sessionLogger!=null){
            sessionLogger.addHandler(sh);
        }
    }

    /**
     * INTERNAL:
     * Return the name space for the given category from the map.
     */
    protected String getNameSpaceString(String category) {
        if (session == null) {
            return DEFAULT_TOPLINK_NAMESPACE;
        } else if ((category == null) || (category.length() == 0)) {
            return sessionNameSpace;
        } else {
            return  (String)nameSpaceMap.get(category);
        }
    }

    /**
     * INTERNAL:
     * Return the Logger for the given category
     */
    protected Logger getLogger(String category) {
        if (session == null) {
            return (Logger)categoryloggers.get(DEFAULT_TOPLINK_NAMESPACE);
        } else if ((category == null) || (category.length() == 0) || !this.categoryloggers.containsKey(category)) {
            return (Logger) categoryloggers.get(sessionNameSpace);
        } else {
            Logger logger = (Logger) categoryloggers.get(category);
            // If session != null, categoryloggers should have an entry for this category
            assert logger != null;
            return logger;
        }
    }

    /**
     * PUBLIC:
     * <p>
     * Set the session and session namespace.
     * </p>
     *
     * @param session  a Session
     */
    @Override
    public void setSession(Session session) {
        super.setSession(session);
        if (session != null) {
            String sessionName = session.getName();
            if ((sessionName != null) && (sessionName.length() != 0)) {
                sessionNameSpace = SESSION_TOPLINK_NAMESPACE + "." + sessionName;
            } else {
                sessionNameSpace = DEFAULT_TOPLINK_NAMESPACE;
            }

            //Initialize loggers eagerly
            addLogger(sessionNameSpace, sessionNameSpace);
             for (int i = 0; i < loggerCatagories.length; i++) {
                String loggerCategory =  loggerCatagories[i];
                String loggerNameSpace = sessionNameSpace + "." + loggerCategory;
                nameSpaceMap.put(loggerCategory, loggerNameSpace);
                addLogger(loggerCategory, loggerNameSpace);
            }
        }
    }

    /**
     * INTERNAL:
     * Return the corresponding java.util.logging.Level for a given TopLink level.
     */
    protected Level getJavaLevel(int level) {
        return levels[level];
    }

    /**
     * PUBLIC:
     * <p>
     * Check if a message of the given level would actually be logged by the logger
     * with name space built from the given session and category.
     * Return the shouldLog for the given category from
     * </p>
     * @return true if the given message level will be logged
     */
    @Override
    public boolean shouldLog(int level, String category) {
        Logger logger = getLogger(category);
        return logger.isLoggable(getJavaLevel(level));
    }

    /**
     * PUBLIC:
     * <p>
     * Log a SessionLogEntry
     * </p>
     * @param entry SessionLogEntry that holds all the information for a TopLink logging event
     */
    @Override
    public void log(SessionLogEntry entry) {
        if (!shouldLog(entry.getLevel(), entry.getNameSpace())) {
            return;
        }

        Logger logger = getLogger(entry.getNameSpace());
        Level javaLevel = getJavaLevel(entry.getLevel());

        internalLog(entry, javaLevel, logger);
    }

    /**
     * INTERNAL:
     * <p>
     * Build a LogRecord
     * </p>
     * @param entry SessionLogEntry that holds all the information for a TopLink logging event
     * @param javaLevel the message level
     */
    protected void internalLog(SessionLogEntry entry, Level javaLevel, Logger logger) {
        // Format message so that we do not depend on the bundle
        EclipseLinkLogRecord lr = new EclipseLinkLogRecord(javaLevel, formatMessage(entry));

        lr.setSourceClassName(entry.getSourceClassName());
        lr.setSourceMethodName(entry.getSourceMethodName());
        lr.setLoggerName(getNameSpaceString(entry.getNameSpace()));
        if (shouldPrintSession()) {
            lr.setSessionString(getSessionString(entry.getSession()));
        }
        if (shouldPrintConnection()) {
            lr.setConnection(entry.getConnection());
        }
        lr.setThrown(entry.getException());
        lr.setShouldLogExceptionStackTrace(shouldLogExceptionStackTrace());
        lr.setShouldPrintDate(shouldPrintDate());
        lr.setShouldPrintThread(shouldPrintThread());
        logger.log(lr);
    }

    /**
     * PUBLIC:
     * <p>
     * Log a throwable.
     * </p>
     * @param throwable a throwable
     */
    @Override
    public void throwing(Throwable throwable) {
        getLogger(null).throwing(null, null, throwable);
    }

    /**
     * INTERNAL:
     * Each session owns its own session log because session is stored in the session log
     */
    @Override
    public Object clone() {
        // There is no special treatment required for cloning here
        // The state of this object is described  by member variables sessionLogger and categoryLoggers.
        // This state depends on session.
        // If session for the clone is going to be the same as session for this there is no
        // need to do "deep" cloning.
        // If not, the session being cloned should call setSession() on its JavaLog object to initialize it correctly.
        JavaLog cloneLog = (JavaLog)super.clone();
        return cloneLog;
    }
}
