/*
 * 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.felix.eventadmin.impl.util;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;

/**
 * This class mimics the standard OSGi <tt>LogService</tt> interface. An
 * instance of this class will be used by the EventAdmin for all logging. The
 * implementation of this class sends log messages to standard output, if no
 * <tt>LogService</tt> is present; it uses a log service if one is
 * installed in the framework. To do that without creating a hard dependency on the
 * package it uses fully qualified class names and registers a listener with the
 * framework hence, it does not need access to the <tt>LogService</tt> class but will
 * use it if the listener is informed about an available service. By using a
 * DynamicImport-Package dependency we don't need the package but
 * use it if present. Additionally, all log methods prefix the log message with
 * <tt>EventAdmin: </tt>.
 *
 * There is one difference in behavior from the standard OSGi LogService.
 * This logger has a {@link #m_logLevel} property which decides what messages
 * get logged.
 *
 * @see org.osgi.service.log.LogService
 *
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
**/
// TODO: At the moment we log a message to all currently available LogServices.
//       Maybe, we should only log to the one with the highest ranking instead?
//       What is the best practice in this case?
public class LogWrapper
{
    /**
     * ERROR LEVEL
     *
     * @see org.osgi.service.log.LogService#LOG_ERROR
     */
    public static final int LOG_ERROR = 1;

    /**
     * WARNING LEVEL
     *
     * @see org.osgi.service.log.LogService#LOG_WARNING
     */
    public static final int LOG_WARNING = 2;

    /**
     * INFO LEVEL
     *
     * @see org.osgi.service.log.LogService#LOG_INFO
     */
    public static final int LOG_INFO = 3;

    /**
     * DEBUG LEVEL
     *
     * @see org.osgi.service.log.LogService#LOG_DEBUG
     */
    public static final int LOG_DEBUG = 4;

    // A set containing the currently available LogServices. Furthermore used as lock
    private final Set<ServiceReference> m_loggerRefs = new HashSet<ServiceReference>();

    // Only null while not set and m_loggerRefs is empty hence, only needs to be
    // checked in case m_loggerRefs is empty otherwise it will not be null.
    private BundleContext m_context;

    private ServiceListener m_logServiceListener;

    /**
     * Current log level. Message with log level less than or equal to
     * current log level will be logged.
     * The default value is {@link #LOG_WARNING}
     *
     * @see #setLogLevel(int)
     */
    private int m_logLevel = LOG_WARNING;
    /*
     * A thread save variant of the double checked locking singleton.
     */
    private static class LogWrapperLoader
    {
        static final LogWrapper m_singleton = new LogWrapper();
    }

    /**
     * Returns the singleton instance of this LogWrapper that can be used to send
     * log messages to all currently available LogServices or to standard output,
     * respectively.
     *
     * @return the singleton instance of this LogWrapper.
     */
    public static LogWrapper getLogger()
    {
        return LogWrapperLoader.m_singleton;
    }

    /**
     * Set the <tt>BundleContext</tt> of the bundle. This method registers a service
     * listener for LogServices with the framework that are subsequently used to
     * log messages.
     * <p>
     * If the bundle context is <code>null</code>, the service listener is
     * unregistered and all remaining references to LogServices dropped before
     * internally clearing the bundle context field.
     *
     *  @param context The context of the bundle.
     */
    public static void setContext( final BundleContext context )
    {
        LogWrapper logWrapper = LogWrapperLoader.m_singleton;

        // context is removed, unregister and drop references
        if ( context == null )
        {
            if ( logWrapper.m_logServiceListener != null )
            {
                logWrapper.m_context.removeServiceListener( logWrapper.m_logServiceListener );
                logWrapper.m_logServiceListener = null;
            }
            logWrapper.removeLoggerRefs();
        }

        // set field
        logWrapper.setBundleContext( context );

        // context is set, register and get existing services
        if ( context != null )
        {
            try
            {
                ServiceListener listener = new ServiceListener()
                {
                    // Add a newly available LogService reference to the singleton.
                    @Override
                    public void serviceChanged( final ServiceEvent event )
                    {
                        if ( ServiceEvent.REGISTERED == event.getType() )
                        {
                            LogWrapperLoader.m_singleton.addLoggerRef( event.getServiceReference() );
                        }
                        // unregistered services are handled in the next log operation.
                    }

                };
                context.addServiceListener( listener, "(" + Constants.OBJECTCLASS + "=org.osgi.service.log.LogService)" );
                logWrapper.m_logServiceListener = listener;

                // Add all available LogService references to the singleton.
                final ServiceReference[] refs = context.getServiceReferences( "org.osgi.service.log.LogService", null );

                if ( null != refs )
                {
                    for ( int i = 0; i < refs.length; i++ )
                    {
                        logWrapper.addLoggerRef( refs[i] );
                    }
                }
            }
            catch ( InvalidSyntaxException e )
            {
                // this never happens
            }
        }
    }


    /*
     * The private singleton constructor.
     */
    LogWrapper()
    {
        // Singleton
    }

    /*
     * Removes all references to LogServices still kept
     */
    void removeLoggerRefs()
    {
        synchronized ( m_loggerRefs )
        {
            m_loggerRefs.clear();
        }
    }

    /*
     * Add a reference to a newly available LogService
     */
    void addLoggerRef( final ServiceReference ref )
    {
        synchronized (m_loggerRefs)
        {
            m_loggerRefs.add(ref);
        }
    }

    /*
     * Set the context of the bundle in the singleton implementation.
     */
    private void setBundleContext(final BundleContext context)
    {
        synchronized(m_loggerRefs)
        {
            m_context = context;
        }
    }

    /**
     * Log a message with the given log level. Note that this will prefix the message
     * with <tt>EventAdmin: </tt>.
     *
     * @param level The log level with which to log the msg.
     * @param msg The message to log.
     */
    public void log(final int level, final String msg)
    {
        // The method will remove any unregistered service reference as well.
        synchronized(m_loggerRefs)
        {
            if (level > m_logLevel)
            {
                return; // don't log
            }

            final String logMsg = "EventAdmin: " + msg;

            if (!m_loggerRefs.isEmpty())
            {
                // There is at least one LogService available hence, we can use the
                // class as well.
                for (Iterator<ServiceReference> iter = m_loggerRefs.iterator(); iter.hasNext();)
                {
                    final ServiceReference next = iter.next();

                    org.osgi.service.log.LogService logger =
                        (org.osgi.service.log.LogService) m_context.getService(next);

                    if (null != logger)
                    {
                        logger.log(level, logMsg);

                        m_context.ungetService(next);
                    }
                    else
                    {
                        // The context returned null for the reference - it follows
                        // that the service is unregistered and we can remove it
                        iter.remove();
                    }
                }
            }
            else
            {
                _log(null, level, logMsg, null);
            }
        }
    }

    /**
     * Log a message with the given log level and the associated exception. Note that
     * this will prefix the message with <tt>EventAdmin: </tt>.
     *
     * @param level The log level with which to log the msg.
     * @param msg The message to log.
     * @param ex The exception associated with the message.
     */
    public void log(final int level, final String msg, final Throwable ex)
    {
        // The method will remove any unregistered service reference as well.
        synchronized(m_loggerRefs)
        {
            if (level > m_logLevel)
            {
                return; // don't log
            }

            final String logMsg = "EventAdmin: " + msg;

            if (!m_loggerRefs.isEmpty())
            {
                // There is at least one LogService available hence, we can use the
                // class as well.
                for (Iterator<ServiceReference> iter = m_loggerRefs.iterator(); iter.hasNext();)
                {
                    final ServiceReference next = iter.next();

                    org.osgi.service.log.LogService logger =
                        (org.osgi.service.log.LogService) m_context.getService(next);

                    if (null != logger)
                    {
                        logger.log(level, logMsg, ex);

                        m_context.ungetService(next);
                    }
                    else
                    {
                        // The context returned null for the reference - it follows
                        // that the service is unregistered and we can remove it
                        iter.remove();
                    }
                }
            }
            else
            {
                _log(null, level, logMsg, ex);
            }
        }
    }

    /**
     * Log a message with the given log level together with the associated service
     * reference. Note that this will prefix the message with <tt>EventAdmin: </tt>.
     *
     * @param sr The reference of the service associated with this message.
     * @param level The log level with which to log the msg.
     * @param msg The message to log.
     */
    public void log(final ServiceReference sr, final int level, final String msg)
    {
        // The method will remove any unregistered service reference as well.
        synchronized(m_loggerRefs)
        {
            if (level > m_logLevel)
            {
                return; // don't log
            }

            final String logMsg = "EventAdmin: " + msg;

            if (!m_loggerRefs.isEmpty())
            {
                // There is at least one LogService available hence, we can use the
                // class as well.
                for (Iterator<ServiceReference> iter = m_loggerRefs.iterator(); iter.hasNext();)
                {
                    final ServiceReference next = iter.next();

                    org.osgi.service.log.LogService logger =
                        (org.osgi.service.log.LogService) m_context.getService(next);

                    if (null != logger)
                    {
                        logger.log(sr, level, logMsg);

                        m_context.ungetService(next);
                    }
                    else
                    {
                        // The context returned null for the reference - it follows
                        // that the service is unregistered and we can remove it
                        iter.remove();
                    }
                }
            }
            else
            {
                _log(sr, level, logMsg, null);
            }
        }
    }

    /**
     * Log a message with the given log level, the associated service reference and
     * exception. Note that this will prefix the message with <tt>EventAdmin: </tt>.
     *
     * @param sr The reference of the service associated with this message.
     * @param level The log level with which to log the msg.
     * @param msg The message to log.
     * @param ex The exception associated with the message.
     */
    public void log(final ServiceReference sr, final int level, final String msg,
        final Throwable ex)
    {
        // The method will remove any unregistered service reference as well.
        synchronized(m_loggerRefs)
        {
            if (level > m_logLevel)
            {
                return; // don't log
            }

            final String logMsg = "EventAdmin: " + msg;

            if (!m_loggerRefs.isEmpty())
            {
                // There is at least one LogService available hence, we can use the
                // class as well.
                for (Iterator<ServiceReference> iter = m_loggerRefs.iterator(); iter.hasNext();)
                {
                       final ServiceReference next = iter.next();

                    org.osgi.service.log.LogService logger =
                        (org.osgi.service.log.LogService) m_context.getService(next);

                    if (null != logger)
                    {
                        logger.log(sr, level, logMsg, ex);

                        m_context.ungetService(next);
                    }
                    else
                    {
                        // The context returned null for the reference - it follows
                        // that the service is unregistered and we can remove it
                        iter.remove();
                    }
                }
            }
            else
            {
                _log(sr, level, logMsg, ex);
            }
        }
    }

    /*
     * Log the message to standard output. This appends the level to the message.
     * null values are handled appropriate.
     */
    private void _log(final ServiceReference sr, final int level, final String msg,
        Throwable ex)
    {
        String s = (sr == null) ? null : "SvcRef " + sr;
        s = (s == null) ? msg : s + " " + msg;
        s = (ex == null) ? s : s + " (" + ex + ")";

        switch (level)
        {
            case LOG_DEBUG:
                System.out.println("DEBUG: " + s);
                break;
            case LOG_ERROR:
                System.out.println("ERROR: " + s);
                if (ex != null)
                {
                    if ((ex instanceof BundleException)
                        && (((BundleException) ex).getNestedException() != null))
                    {
                        ex = ((BundleException) ex).getNestedException();
                    }

                    ex.printStackTrace();
                }
                break;
            case LOG_INFO:
                System.out.println("INFO: " + s);
                break;
            case LOG_WARNING:
                System.out.println("WARNING: " + s);
                break;
            default:
                System.out.println("UNKNOWN[" + level + "]: " + s);
        }
    }

    /**
     * Change the current log level. Log level decides what messages gets
     * logged. Any message with a log level higher than the currently set
     * log level is not logged.
     *
     * @param logLevel new log level
     */
    public void setLogLevel(int logLevel)
    {
        synchronized (m_loggerRefs)
        {
            m_logLevel = logLevel;
        }
    }

    /**
     * @return current log level.
     */
    public int getLogLevel()
    {
        synchronized (m_loggerRefs)
        {
            return m_logLevel;
        }
    }
}
