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

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
import java.util.List;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.service.log.LogLevel;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;

public class ConfigurationListenerImpl {
    private static final String CONFIGURATION_CLASS = "org.osgi.service.cm.Configuration";
    private static final String CONFIGURATION_ADMIN_CLASS = "org.osgi.service.cm.ConfigurationAdmin";
    private static final String CONFIGURATION_EVENT_CLASS = "org.osgi.service.cm.ConfigurationEvent";
    private static final String CONFIGURATION_LISTENER_CLASS = "org.osgi.service.cm.ConfigurationListener";
    private static final String LOGGER_ADMIN_PID = "org.osgi.service.log.admin";
    private static final String LOGGER_ADMIN_PID_PREFIX = LOGGER_ADMIN_PID + '|';

    /** ConfigurationAdmin tracker */
    final ServiceTracker<?, ?> m_cmtracker;
    final BundleContext m_context;
    final Log m_log;
    final LoggerAdminImpl m_loggerAdmin;

    public ConfigurationListenerImpl(final BundleContext context, final Log log, final LoggerAdminImpl loggerAdmin) throws Exception {
        m_context = context;
        m_log = log;
        m_loggerAdmin = loggerAdmin;

        Filter filter = context.createFilter(String.format("(%s=%s)", Constants.OBJECTCLASS, CONFIGURATION_ADMIN_CLASS));

        m_cmtracker = new ServiceTracker<>(m_context, filter, new CLCustomizer());
        m_cmtracker.open();
    }

    public void close() {
        m_cmtracker.close();
    }

    class CLProxy {
        private final Object m_ca;
        private final ServiceReference<?> m_caReference;
        private final ServiceRegistration<?> m_registration;
        private final Class<?> m_caClass;
        private final Class<?> m_ceClass;
        private final Class<?> m_clClass;
        private final Class<?> m_configurationClass;
        private final Method m_caGetConfiguration;
        private final Method m_caListConfigurations;
        private final Method m_ceGetPid;
        private final Method m_ceGetType;
        private final Method m_clConfigurationEvent;
        private final Method m_configurationGetProperties;
        private final Method m_configurationGetProcessedProperties;

        public CLProxy(ServiceReference<?> caReference) {
            m_caReference = caReference;
            m_ca = m_context.getService(m_caReference);

            final Bundle bundle = m_caReference.getBundle();
            if ( bundle == null )
            {
                throw new IllegalStateException("Service already unregistered again");
            }
            try {
                m_caClass = bundle.loadClass(CONFIGURATION_ADMIN_CLASS);
                m_caGetConfiguration = m_caClass.getMethod("getConfiguration", String.class, String.class);
                m_caListConfigurations = m_caClass.getMethod("listConfigurations", String.class);

                m_configurationClass = bundle.loadClass(CONFIGURATION_CLASS);
                m_configurationGetProperties = m_configurationClass.getMethod("getProperties");
                Method configurationGetProcessedProperties = null;
                try {
                    // try for the 1.6 method
                    configurationGetProcessedProperties = m_configurationClass.getMethod("getProcessedProperties", ServiceReference.class);
                }
                catch (NoSuchMethodException nsme) {
                    // ignore
                }
                m_configurationGetProcessedProperties = configurationGetProcessedProperties;

                m_ceClass = bundle.loadClass(CONFIGURATION_EVENT_CLASS);
                m_ceGetPid = m_ceClass.getMethod("getPid");
                m_ceGetType = m_ceClass.getMethod("getType");

                m_clClass = bundle.loadClass(CONFIGURATION_LISTENER_CLASS);
                m_clConfigurationEvent = m_clClass.getMethod("configurationEvent", m_ceClass);
            }
            catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) {
                throw new IllegalStateException(
                    "Failure reflecting over API from Configuration Admin service bundle", e);
            }

            m_registration = m_context.registerService(CONFIGURATION_LISTENER_CLASS, configurationListenerProxy(), null);
        }

        private Object configurationListenerProxy() {
            ClassLoader classLoader = m_caReference.getBundle().adapt(BundleWiring.class).getClassLoader();

            return Proxy.newProxyInstance(
                classLoader, new Class<?>[] {m_clClass},
                new InvocationHandler() {

                    @SuppressWarnings("unchecked")
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if (method.equals(m_clConfigurationEvent)) {
                            String pid = (String)m_ceGetPid.invoke(args[0]);
                            if(!pid.startsWith(LOGGER_ADMIN_PID)) {
                            	return null;
                            }
                            String configName = null;
                            String location = "?";
                            if (pid.startsWith(LOGGER_ADMIN_PID_PREFIX)) {
                                configName = pid.substring(LOGGER_ADMIN_PID_PREFIX.length());
                                if (configName.contains("|") && (configName.split("|").length == 3)) {
                                    String[] parts = configName.split("|");
                                    location = parts[2];
                                }
                            }

                            switch ((int)m_ceGetType.invoke(args[0])) {
                                case 2: // CM_DELETED
                                    m_loggerAdmin.updateConfiguration(configName, null);
                                    break;
                                default:
                                    Object configObj = m_caGetConfiguration.invoke(m_ca, pid, location);
                                    Object propertiesObj = getProperties(configObj);
                                    m_loggerAdmin.updateConfiguration(configName, (Dictionary<String, Object>)propertiesObj);
                            }
                        }

                        return null;
                    }
                }
            );
        }

        @SuppressWarnings("unchecked")
        private Dictionary<String, Object> getProperties(Object configObj) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            if (m_configurationGetProcessedProperties != null) {
                return (Dictionary<String, Object>) m_configurationGetProcessedProperties.invoke(configObj, m_caReference);
            }
            return (Dictionary<String, Object>) m_configurationGetProperties.invoke(configObj);
        }

        @SuppressWarnings("rawtypes")
        private List<Dictionary> listConfigurations(String filter) {
            try {
                Object result = m_caListConfigurations.invoke(m_ca, filter);
                if (result != null) {
                    List<Dictionary> dictionaries = new ArrayList<>();
                    for (Object configObj : (Object[])result) {
                        dictionaries.add(getProperties(configObj));
                    }
                    return dictionaries;
                }
            }
            catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                if (e instanceof InvocationTargetException) {
                    m_log.log(getClass().getName(), m_context.getBundle(), null, LogLevel.ERROR, "An error occured reflecting on ConfigurationAdmin.", ((InvocationTargetException)e).getTargetException());
                }
                else {
                    m_log.log(getClass().getName(), m_context.getBundle(), null, LogLevel.ERROR, "An error occured reflecting on ConfigurationAdmin.", e);
                }
            }
            return Collections.emptyList();
        }

        private void unregister() {
            m_registration.unregister();
        }

        @SuppressWarnings({ "rawtypes", "unchecked" })
        private void updateContext(String name, String pid, boolean delete) {
            List<Dictionary> configurations = listConfigurations(String.format("(%s=%s)", Constants.SERVICE_PID, pid));

            if (!configurations.isEmpty()) {
                m_loggerAdmin.updateConfiguration(name, delete ? null : configurations.get(0));
            }
        }

    }

    class CLCustomizer implements ServiceTrackerCustomizer<Object, CLProxy> {

        @Override
        public CLProxy addingService(ServiceReference<Object> reference) {
            CLProxy clProxy = new CLProxy(reference);

            // configure ROOT context
            clProxy.updateContext(null, "org.osgi.service.log.admin", false);

            // configure bundle contexts
            for (String name : m_loggerAdmin.getLoggerContextNames()) {
                String pid = "org.osgi.service.log.admin|" + name;
                clProxy.updateContext(name, pid, false);
            }

            return clProxy;
        }

        @Override
        public void modifiedService(ServiceReference<Object> reference, CLProxy clProxy) {
        }

        @Override
        public void removedService(ServiceReference<Object> reference, CLProxy clProxy) {
            // un-configure bundle contexts
            for (String name : m_loggerAdmin.getLoggerContextNames()) {
                String pid = "org.osgi.service.log.admin|" + name;
                clProxy.updateContext(name, pid, true);
            }

            // un-configure ROOT context
            clProxy.updateContext(null, "org.osgi.service.log.admin", true);

            // un-register the configuration listener
            clProxy.unregister();
        }

    }

}
