/**
 * Licensed 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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.winegrower.service;

import static java.util.Collections.list;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Stream;

import org.apache.winegrower.Ripener;
import org.apache.winegrower.api.InjectedService;
import org.apache.winegrower.deployer.BundleContextImpl;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.PrototypeServiceFactory;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.hooks.service.EventListenerHook;
import org.osgi.framework.hooks.service.FindHook;
import org.osgi.framework.hooks.service.ListenerHook;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ConfigurationListener;
import org.osgi.service.cm.ManagedService;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;
import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

// holder of all services
public class OSGiServices {
    private static final Logger LOGGER = LoggerFactory.getLogger(OSGiServices.class);

    private final AtomicLong idGenerator = new AtomicLong(1);

    private final Collection<ServiceListenerDefinition> serviceListeners = new ArrayList<>();
    private final Collection<ServiceRegistrationImpl<?>> services = new ArrayList<>();
    private final Hooks hooks = new Hooks();
    private final Collection<ConfigurationListener> configurationListeners;
    private final Collection<DefaultEventAdmin.EventHandlerInstance> eventListeners;
    private final Ripener framework;

    public OSGiServices(final Ripener framework,
                        final Collection<ConfigurationListener> configurationListeners,
                        final Collection<DefaultEventAdmin.EventHandlerInstance> eventListeners) {
        this.framework = framework;
        this.configurationListeners = configurationListeners;
        this.eventListeners = eventListeners;
    }

    public Hooks getHooks() {
        return hooks;
    }

    public <T> T inject(final T instance) {
        doInject(instance.getClass(), instance);
        return instance;
    }

    private <T> void doInject(final Class<?> typeScope, final T instance) {
        if (typeScope == null || typeScope == Object.class) {
            return;
        }
        Stream.of(typeScope.getDeclaredFields())
              .filter(field -> field.isAnnotationPresent(InjectedService.class))
              .peek(field -> {
                  if (!field.isAccessible()) {
                      field.setAccessible(true);
                  }
              })
              .forEach(field -> {
                  if (Ripener.class == field.getType()) {
                      try {
                          field.set(instance, framework);
                      } catch (final IllegalAccessException e) {
                          throw new IllegalStateException(e);
                      }
                  } else if (OSGiServices.class == field.getType()) {
                      try {
                          field.set(instance, framework.getServices());
                      } catch (final IllegalAccessException e) {
                          throw new IllegalStateException(e);
                      }
                  } else {
                      findService(field.getType())
                              .ifPresent(value -> {
                                  try {
                                      field.set(instance, value);
                                  } catch (final IllegalAccessException e) {
                                      throw new IllegalStateException(e);
                                  }
                              });
                  }
              });
        doInject(typeScope.getSuperclass(), instance);
    }

    public <T> Optional<T> findService(final Class<T> type) {
        final Bundle bundle = framework.getRegistry().getBundles().get(0L).getBundle();
        final ServiceTracker<T, T> tracker = new ServiceTracker<>(bundle.getBundleContext(), type, null);
        tracker.open();
        try {
            return ofNullable(tracker.waitForService(0L));
        } catch (final InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new IllegalStateException(e);
        }
    }

    public synchronized void addListener(final ServiceListener listener, final Filter filter,
                                         final BundleContext context) {
        serviceListeners.add(new ServiceListenerDefinition(listener, filter, context));
    }

    public synchronized void removeListener(final ServiceListener listener) {
        serviceListeners.removeIf(d -> d.listener == listener);
    }

    public synchronized ServiceRegistration<?> registerService(final String[] classes, final Object service,
                                                               final Dictionary<String, ?> properties,
                                                               final Bundle from) {
        final Hashtable<String, Object> serviceProperties = new Hashtable<String, Object>() {
            @Override
            public Object get(final Object key) {
                final String property = System.getProperty(String.valueOf(key));
                return property != null ? property : super.get(key);
            }
        };
        if (properties != null) {
            list(properties.keys()).forEach(key -> serviceProperties.put(key, properties.get(key)));
        }
        serviceProperties.put(Constants.OBJECTCLASS, classes.length == 1 ? classes[0] : classes);
        serviceProperties.put(Constants.SERVICE_ID, idGenerator.getAndIncrement());
        serviceProperties.put(Constants.SERVICE_BUNDLEID, from.getBundleId());
        if (ServiceFactory.class.isInstance(service)) {
            serviceProperties.put(Constants.SERVICE_SCOPE, PrototypeServiceFactory.class.isInstance(service) ?
                    Constants.SCOPE_PROTOTYPE : Constants.SCOPE_BUNDLE);
        } else {
            serviceProperties.put(Constants.SERVICE_SCOPE, Constants.SCOPE_SINGLETON);
        }

        final boolean isConfigListener = Stream.of(classes).anyMatch(it -> it.equals(ConfigurationListener.class.getName()));
        if (isConfigListener) {
            synchronized (configurationListeners) {
                configurationListeners.add(ConfigurationListener.class.cast(service));
            }
        }

        boolean isEventHandler = Stream.of(classes).anyMatch(it -> it.equals(EventHandler.class.getName()));
        final boolean removeEventHandler = isEventHandler;
        final boolean serviceFindHook = Stream.of(classes).anyMatch(it -> it.equals(FindHook.class.getName()));
        final boolean bundleFindHook = Stream.of(classes).anyMatch(it -> it.equals(org.osgi.framework.hooks.bundle.FindHook.class.getName()));
        final boolean eventListenerHook = Stream.of(classes).anyMatch(it -> it.equals(EventListenerHook.class.getName()));
        final ServiceReferenceImpl<Object> ref = new ServiceReferenceImpl<>(serviceProperties, from, service);
        final ServiceRegistrationImpl<Object> registration = new ServiceRegistrationImpl<>(classes,
                serviceProperties, ref, reg -> {
            final ServiceEvent event = new ServiceEvent(ServiceEvent.UNREGISTERING, reg.getReference());
            fireEvent(reg, event);
            synchronized (OSGiServices.this) {
                services.remove(reg);
            }

            if (isConfigListener) {
                synchronized (configurationListeners) {
                    configurationListeners.remove(ConfigurationListener.class.cast(service));
                }
            }
            if (removeEventHandler) {
                synchronized (eventListeners) {
                    eventListeners.removeIf(it -> it.getHandler() == service);
                }
            }
            if (serviceFindHook) {
                hooks.getServiceFindHooks().remove(ref);
            }
            if (bundleFindHook) {
                hooks.getBundleFindHooks().remove(ref);
            }
            if (eventListenerHook) {
                hooks.getEventListenerHooks().remove(ref);
            }
        });

        if (isEventHandler) {
            final Object topics = properties.get(EventConstants.EVENT_TOPIC);
            final String[] topicsArray = String[].class.isInstance(topics) ?
                    String[].class.cast(topics) :
                    (String.class.isInstance(topics) ? new String[]{ String.class.cast(topics)} :
                    Collection.class.isInstance(properties) ?
                            ((Collection<Object>) topics).stream().map(String::valueOf).toArray(String[]::new) :
                            null);
            if (topics == null) {
                LOGGER.warn("No topic for {}", service);
            } else {
                synchronized (eventListeners) {
                    eventListeners.add(new DefaultEventAdmin.EventHandlerInstance(
                            from,
                            EventHandler.class.isInstance(service) ?
                                    EventHandler.class.cast(service) :
                                    new DefaultEventAdmin.EventHandlerFactory(
                                            from, ServiceRegistration.class.cast(registration),
                                            ServiceFactory.class.cast(service)),
                            Stream.of(topicsArray).anyMatch("*"::equals) ? null : topicsArray,
                            ofNullable(properties.get(EventConstants.EVENT_FILTER)).map(String::valueOf).orElse(null)));
                }
            }
        }

        final Object pid = serviceProperties.get(Constants.SERVICE_PID);
        if (pid != null) {
            final ConfigurationAdmin configurationAdmin = framework.getConfigurationAdmin();
            final String pidStr = String.valueOf(pid);
            try {
                final Configuration configuration = configurationAdmin.getConfiguration(pidStr);
                ofNullable(configuration.getProperties())
                        .ifPresent(prop -> list(prop.keys())
                                .forEach(key -> serviceProperties.put(key, configuration.getProperties().get(key))));
            } catch (final IOException e) {
                LOGGER.warn(e.getMessage());
            }
        }

        final Object factoryPid = serviceProperties.get("service.factoryPid");
        if (factoryPid != null) {
            final ConfigurationAdmin configurationAdmin = framework.getConfigurationAdmin();
            final String pidStr = String.valueOf(factoryPid);
            try {
                final Configuration configuration = configurationAdmin.createFactoryConfiguration(pidStr);
                ofNullable(configuration.getProperties())
                        .ifPresent(prop -> list(prop.keys())
                                .forEach(key -> serviceProperties.put(key, configuration.getProperties().get(key))));
            } catch (final IOException e) {
                LOGGER.warn(e.getMessage());
            }
        }

        services.add(registration);

        final ServiceEvent event = new ServiceEvent(ServiceEvent.REGISTERED, ref);
        if (ManagedService.class.isInstance(service)) {
            try {
                ManagedService.class.cast(service).updated(serviceProperties);
            } catch (final ConfigurationException e) {
                throw new IllegalStateException(e);
            }
        }
        fireEvent(registration, event);

        if (serviceFindHook) {
            hooks.getServiceFindHooks().add(ServiceReference.class.cast(ref));
        }
        if (bundleFindHook) {
            hooks.getBundleFindHooks().add(ServiceReference.class.cast(ref));
        }
        if (eventListenerHook) {
            hooks.getEventListenerHooks().add(ServiceReference.class.cast(ref));
        }

        return registration;
    }

    private void fireEvent(final ServiceRegistration<?> reg, final ServiceEvent event) {
        final List<ServiceListenerDefinition> listeners = getListeners(reg);
        final Collection<ServiceReference<EventListenerHook>> eventListenerHooks = hooks.getEventListenerHooks();
        if (!eventListenerHooks.isEmpty() && !listeners.isEmpty()) {
            eventListenerHooks.forEach(hook -> {
                final BundleContext bundleContext = hook.getBundle().getBundleContext();
                final EventListenerHook instance = bundleContext.getService(hook);
                if (instance != null) {
                    try {
                        final Map<BundleContext, ? extends Collection<ListenerHook.ListenerInfo>> listenerInfo = listeners.stream()
                                .collect(groupingBy(ServiceListenerDefinition::getBundleContext, toList()));
                        instance.event(event, (Map<BundleContext, Collection<ListenerHook.ListenerInfo>>) listenerInfo);
                    } catch (final Throwable th) {
                        LoggerFactory.getLogger(BundleContextImpl.class).warn("Can't call '{}'", hook, th);
                    } finally {
                        bundleContext.ungetService(hook);
                    }
                }
            });
        }
        listeners.forEach(listener -> listener.listener.serviceChanged(event));
    }

    private List<ServiceListenerDefinition> getListeners(final ServiceRegistration<?> reg) {
        return serviceListeners.stream()
                .filter(it -> it.filter == null || it.filter.match(reg.getReference()))
                .collect(toList());
    }

    public synchronized Collection<ServiceRegistration<?>> getServices() {
        return new ArrayList<>(services);
    }

    private static class ServiceListenerDefinition implements ListenerHook.ListenerInfo {
        private final ServiceListener listener;
        private final Filter filter;
        private final BundleContext context;

        private ServiceListenerDefinition(final ServiceListener listener, final Filter filter,
                                          final BundleContext context) {
            this.listener = listener;
            this.filter = filter;
            this.context = context;
        }

        @Override
        public String toString() {
            return "ServiceListenerDefinition{listener=" + listener + ", filter=" + filter + '}';
        }

        @Override
        public BundleContext getBundleContext() {
            return context;
        }

        @Override
        public String getFilter() {
            return filter.toString();
        }

        @Override
        public boolean isRemoved() {
            return false;
        }
    }
}
