/*
 * 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.sling.resourceresolver.impl.providers;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.sling.api.SlingConstants;
import org.apache.sling.api.resource.observation.ResourceChange;
import org.apache.sling.api.resource.observation.ResourceChange.ChangeType;
import org.apache.sling.api.resource.path.Path;
import org.apache.sling.api.resource.path.PathSet;
import org.apache.sling.api.resource.runtime.dto.AuthType;
import org.apache.sling.api.resource.runtime.dto.FailureReason;
import org.apache.sling.api.resource.runtime.dto.ResourceProviderDTO;
import org.apache.sling.api.resource.runtime.dto.ResourceProviderFailureDTO;
import org.apache.sling.api.resource.runtime.dto.RuntimeDTO;
import org.apache.sling.resourceresolver.impl.legacy.LegacyResourceProviderWhiteboard;
import org.apache.sling.spi.resource.provider.ObservationReporter;
import org.apache.sling.spi.resource.provider.ResourceProvider;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This service keeps track of all resource providers.
 */
public class ResourceProviderTracker implements ResourceProviderStorageProvider {

    public interface ObservationReporterGenerator {

        ObservationReporter create(final Path path, final PathSet excludes);

        ObservationReporter createProviderReporter();
    }

    public interface ChangeListener {

        void providerAdded();

        void providerRemoved(String name, String pid, boolean stateful, boolean used);
    }

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @SuppressWarnings("rawtypes")
    private final Map<ServiceReference<ResourceProvider>, ResourceProviderInfo> infos = new ConcurrentHashMap<>();

    private volatile BundleContext bundleContext;

    @SuppressWarnings("rawtypes")
    private volatile ServiceTracker<ResourceProvider, ServiceReference<ResourceProvider>> tracker;

    private final Map<String, List<ResourceProviderHandler>> handlers = new HashMap<>();

    private final Map<ResourceProviderInfo, FailureReason> invalidProviders = new ConcurrentHashMap<>();

    private volatile EventAdmin eventAdmin;

    private volatile ObservationReporterGenerator reporterGenerator;

    private volatile ResourceProviderStorage storage;

    private volatile ObservationReporter providerReporter;

    private volatile ChangeListener listener;

    @SuppressWarnings("rawtypes")
    public void activate(final BundleContext bundleContext, final EventAdmin eventAdmin, final ChangeListener listener) {
        this.bundleContext = bundleContext;
        this.eventAdmin = eventAdmin;
        this.listener = listener;
        this.tracker = new ServiceTracker<>(bundleContext,
                ResourceProvider.class,
                new ServiceTrackerCustomizer<ResourceProvider, ServiceReference<ResourceProvider>>() {

            @Override
            public void removedService(final ServiceReference<ResourceProvider> reference, final ServiceReference<ResourceProvider> ref) {
                final ResourceProviderInfo info = infos.remove(ref);
                if ( info != null ) {
                    Object pid = ref.getProperty(Constants.SERVICE_PID);
                    if ( pid != null && !(pid instanceof String) ) {
                        pid = null;
                    }
                    unregister(info, (String)pid);
                }
            }

            @Override
            public void modifiedService(final ServiceReference<ResourceProvider> reference, final ServiceReference<ResourceProvider> service) {
                removedService(reference, service);
                addingService(reference);
            }

            @Override
            public ServiceReference<ResourceProvider> addingService(final ServiceReference<ResourceProvider> reference) {
                final ResourceProviderInfo info = new ResourceProviderInfo(reference);
                infos.put(reference, info);
                register(info);
                return reference;
            }
        });
        this.tracker.open();
    }

    public void deactivate() {
        this.listener = null;
        this.eventAdmin = null;
        this.providerReporter = null;
        if ( this.tracker != null ) {
            this.tracker.close();
            this.tracker = null;
        }
        this.infos.clear();
        this.handlers.clear();
        this.invalidProviders.clear();
    }

    public void setObservationReporterGenerator(final ObservationReporterGenerator generator) {
        this.providerReporter = generator.createProviderReporter();
        synchronized ( this.handlers ) {
            this.reporterGenerator = generator;
            for (List<ResourceProviderHandler> list : handlers.values()) {
                final ResourceProviderHandler h  = list.get(0);
                if (h != null) {
                    updateProviderContext(h);
                    h.update();
                }
            }
        }
    }

    /**
     * Try to register a new resource provider.
     * @param info The resource provider info.
     */
    private void register(final ResourceProviderInfo info) {
        if ( info.isValid() ) {
           logger.debug("Registering new resource provider {}", info);
           final List<ProviderEvent> events = new ArrayList<>();
           boolean providerAdded = false;
           ResourceProviderHandler deactivateHandler = null;

           ResourceProviderHandler activate = null;
           synchronized ( this.handlers ) {
               List<ResourceProviderHandler> matchingHandlers = this.handlers.get(info.getPath());
               if ( matchingHandlers == null ) {
                   matchingHandlers = new ArrayList<>();
                   this.handlers.put(info.getPath(), matchingHandlers);
               }
               final ResourceProviderHandler handler = new ResourceProviderHandler(bundleContext, info);
               matchingHandlers.add(handler);
               Collections.sort(matchingHandlers);
               if ( matchingHandlers.get(0) == handler ) {
                   activate = handler;
               }
           }
           if ( activate != null ) {
               if ( this.activate(activate) ) {
                   providerAdded = true;
                   events.add(new ProviderEvent(true, info));
                   synchronized ( this.handlers ) {
                       storage = null;
                       final List<ResourceProviderHandler> matchingHandlers = this.handlers.get(info.getPath());
                       if ( matchingHandlers != null && matchingHandlers.size() > 1  ) {
                           deactivateHandler = matchingHandlers.get(1);
                       }
                   }
               } else {
                   synchronized ( this.handlers ) {
                       final List<ResourceProviderHandler> matchingHandlers = this.handlers.get(info.getPath());
                       if ( matchingHandlers != null && !matchingHandlers.isEmpty() && matchingHandlers.remove(activate) ) {
                           storage = null;
                       }
                   }
               }
           }

           final ChangeListener cl = this.listener;
           if ( providerAdded && cl != null ) {
               cl.providerAdded();
           }
           // we have to check for deactivated handlers
           if ( deactivateHandler != null ) {
               final ResourceProviderInfo handlerInfo = deactivateHandler.getInfo();
               if ( cl != null ) {
                   Object pid = handlerInfo.getServiceReference().getProperty(Constants.SERVICE_PID);
                   if ( pid != null && !(pid instanceof String) ) {
                       pid = null;
                   }
                   cl.providerRemoved(handlerInfo.getName(), (String)pid,
                               handlerInfo.getAuthType() != AuthType.no,
                                       deactivateHandler.isUsed());
               }
               this.deactivate(deactivateHandler);
               synchronized ( this.handlers ) {
                   storage = null;
               }
               events.add(new ProviderEvent(false, handlerInfo));
           }
           this.postEvents(events);
        } else {
            logger.warn("Ignoring invalid resource provider {}", info);
            this.invalidProviders.put(info, FailureReason.invalid);
        }
    }

    /**
     * Unregister a resource provider.
     * @param info The resource provider info.
     */
    private void unregister(final ResourceProviderInfo info, final String pid) {
        final boolean isInvalid;
        synchronized ( this.invalidProviders ) {
            isInvalid = this.invalidProviders.remove(info) != null;
        }

        if ( !isInvalid ) {
            logger.debug("Unregistering resource provider {}", info);

            // remove provider from handlers and if the provider is active (first handler)
            // keep the reference for deactivation
            ResourceProviderHandler deactivateHandler = null;
            synchronized (this.handlers) {
                final List<ResourceProviderHandler> matchingHandlers = this.handlers.get(info.getPath());
                if ( matchingHandlers != null ) {
                    final Iterator<ResourceProviderHandler> it = matchingHandlers.iterator();
                    boolean first = true;
                    while (it.hasNext()) {
                        final ResourceProviderHandler h = it.next();
                        if (h.getInfo() == info) {
                            it.remove();
                            if ( first ) {
                                deactivateHandler = h;
                            } else {
                                h.dispose();
                            }
                            if (matchingHandlers.isEmpty()) {
                                this.handlers.remove(info.getPath());
                            }
                            storage = null;

                            break;
                        }
                        first = false;
                    }
                }
            }

            if ( deactivateHandler != null ) {
                final List<ProviderEvent> events = new ArrayList<>();
                final ChangeListener cl = this.listener;
                if ( cl != null ) {
                    cl.providerRemoved(info.getName(), pid,
                            info.getAuthType() != AuthType.no,
                                    deactivateHandler.isUsed());
                }
                this.deactivate(deactivateHandler);
                deactivateHandler.dispose();

                // check if we can activate another handler
                ResourceProviderHandler addingProvider = null;
                synchronized ( this.handlers ) {
                    final List<ResourceProviderHandler> matchingHandlers = this.handlers.get(info.getPath());
                    if ( matchingHandlers != null ) {
                        if ( matchingHandlers.isEmpty() ) {
                            this.handlers.remove(info.getPath());
                        } else {
                            addingProvider = matchingHandlers.get(0);
                        }
                    }
                }
                boolean providerAdded = false;
                while ( addingProvider != null ) {
                    if (this.activate(addingProvider)) {
                        events.add(new ProviderEvent(true, addingProvider.getInfo()));
                        providerAdded = true;
                        addingProvider = null;
                        synchronized ( this.handlers ) {
                            this.storage = null;
                        }
                    } else {
                        synchronized ( this.handlers ) {
                            final List<ResourceProviderHandler> matchingHandlers = this.handlers.get(info.getPath());
                            if ( matchingHandlers != null && !matchingHandlers.isEmpty() ) {
                                if ( matchingHandlers.get(0) == addingProvider ) {
                                    this.storage = null;
                                    matchingHandlers.remove(0);
                                    addingProvider.dispose();
                                    if ( matchingHandlers.isEmpty() ) {
                                        this.handlers.remove(info.getPath());
                                        addingProvider = null;
                                    } else {
                                        addingProvider = matchingHandlers.get(0);
                                    }
                                }
                            }
                        }
                    }
                }

                if ( providerAdded && cl != null ) {
                    if ( cl != null ) {
                        cl.providerAdded();
                    }
                }
                events.add(new ProviderEvent(false,info));
                this.postEvents(events);

            }
        } else {
            logger.debug("Unregistering invalid resource provider {}", info);
        }
    }

    /**
     * Activate a resource provider
     * @param handler The provider handler
     */
    private boolean activate(final ResourceProviderHandler handler) {
        synchronized (this.handlers) {
            updateProviderContext(handler);
        }
        if ( !handler.activate() ) {
            logger.warn("Activating resource provider {} failed", handler.getInfo());
            this.invalidProviders.put(handler.getInfo(), FailureReason.service_not_gettable);

            return false;
        }
        logger.debug("Activated resource provider {}", handler.getInfo());
        return true;
    }

    /**
     * Deactivate a resource provider
     * @param handler The provider handler
     */
    private void deactivate(final ResourceProviderHandler handler) {
        handler.deactivate();
        logger.debug("Deactivated resource provider {}", handler.getInfo());
    }

    /**
     * Post a change event through the event admin
     * @param event
     */
    private void postOSGiEvent(final ProviderEvent event) {
        final EventAdmin ea = this.eventAdmin;
        if ( ea != null ) {
            final Dictionary<String, Object> eventProps = new Hashtable<>();
            eventProps.put(SlingConstants.PROPERTY_PATH, event.path);
            if (event.pid != null) {
                eventProps.put(Constants.SERVICE_PID, event.pid);
            }
            ea.postEvent(new Event(event.isAdd ? SlingConstants.TOPIC_RESOURCE_PROVIDER_ADDED : SlingConstants.TOPIC_RESOURCE_PROVIDER_REMOVED,
                    eventProps));
        }
    }

    /**
     * Post a change event for a resource provider change
     * @param type The change type
     * @param info The resource provider
     */
    private void postResourceProviderChange(final ProviderEvent event) {
        final ObservationReporter or = this.providerReporter;
        if ( or != null ) {
            final ResourceChange change = new ResourceChange(event.isAdd ? ChangeType.PROVIDER_ADDED : ChangeType.PROVIDER_REMOVED,
                    event.path, false);
            or.reportChanges(Collections.singletonList(change), false);
        }
    }

    public void fill(final RuntimeDTO dto) {
        final List<ResourceProviderDTO> dtos = new ArrayList<>();
        final List<ResourceProviderFailureDTO> failures = new ArrayList<>();

        synchronized ( this.handlers ) {
            for(final List<ResourceProviderHandler> handlers : this.handlers.values()) {
                boolean isFirst = true;
                for(final ResourceProviderHandler h : handlers) {
                    final ResourceProviderDTO d;
                    if ( isFirst ) {
                        d = new ResourceProviderDTO();
                        dtos.add(d);
                        isFirst = false;
                    } else {
                        d = new ResourceProviderFailureDTO();
                        ((ResourceProviderFailureDTO)d).reason = FailureReason.shadowed;
                        failures.add((ResourceProviderFailureDTO)d);
                    }
                    fill(d, h);
                }
            }
        }
        synchronized ( this.invalidProviders ) {
            for(final Map.Entry<ResourceProviderInfo, FailureReason> entry : this.invalidProviders.entrySet()) {
                final ResourceProviderFailureDTO d = new ResourceProviderFailureDTO();
                fill(d, entry.getKey());
                d.reason = entry.getValue();
                failures.add(d);
            }
        }
        dto.providers = dtos.toArray(new ResourceProviderDTO[dtos.size()]);
        dto.failedProviders = failures.toArray(new ResourceProviderFailureDTO[failures.size()]);
    }

    @Override
    public ResourceProviderStorage getResourceProviderStorage() {
        ResourceProviderStorage result = storage;
        if (result == null) {
            synchronized (this.handlers) {
                if (storage == null) {
                    final List<ResourceProviderHandler> handlerList = new ArrayList<>();
                    for (List<ResourceProviderHandler> list : handlers.values()) {
                        if ( !list.isEmpty() ) {
                            final ResourceProviderHandler h = list.get(0);
                            if (h != null && h.getResourceProvider() != null ) {
                                handlerList.add(h);
                            }
                        }
                    }
                    storage = new ResourceProviderStorage(handlerList);
                }
                result = storage;
            }
        }
        return result;
    }

    private void fill(final ResourceProviderDTO d, final ResourceProviderInfo info) {
        d.adaptable = info.isAdaptable();
        d.attributable = info.isAttributable();
        d.authType = info.getAuthType();
        d.modifiable = info.isModifiable();
        d.name = info.getName();
        d.path = info.getPath();
        d.refreshable = info.isRefreshable();
        d.serviceId = (Long)info.getServiceReference().getProperty(Constants.SERVICE_ID);
        d.supportsQueryLanguage = false;
        d.useResourceAccessSecurity = info.getUseResourceAccessSecurity();
    }

    private void fill(final ResourceProviderDTO d, final ResourceProviderHandler handler) {
        fill(d, handler.getInfo());
        final ResourceProvider<?> provider = handler.getResourceProvider();
        if ( provider != null ) {
            d.supportsQueryLanguage = provider.getQueryLanguageProvider() != null;
        }
    }

    private void updateProviderContext(final ResourceProviderHandler handler) {
        final Set<String> excludedPaths = new HashSet<>();
        final Path handlerPath = new Path(handler.getPath());

        for(final String otherPath : handlers.keySet()) {
            if ( !handler.getPath().equals(otherPath) && handlerPath.matches(otherPath) ) {
                excludedPaths.add(otherPath);
            }
        }

        final PathSet excludedPathSet = PathSet.fromStringCollection(excludedPaths);
        handler.getProviderContext().update(
                reporterGenerator.create(handlerPath, excludedPathSet),
                excludedPathSet);
    }

    private void postEvents(final List<ProviderEvent> events) {
        if ( events.isEmpty() ) {
            return;
        }
        if ( this.listener == null && this.providerReporter == null ) {
            return;
        }
        final Thread t = new Thread(new Runnable() {

            @Override
            public void run() {
                for(final ProviderEvent e : events) {
                    postOSGiEvent(e);
                    postResourceProviderChange(e);
                }
            }
        });
        t.setName("Apache Sling Resource Provider Change Notifier");
        t.setDaemon(true);

        t.start();
    }

    private static final class ProviderEvent {
        public final boolean isAdd;
        public final Object pid;
        public final String path;

        public ProviderEvent(final boolean isAdd, final ResourceProviderInfo info) {
            this.isAdd = isAdd;
            this.path = info.getPath();
            Object pid = info.getServiceReference().getProperty(Constants.SERVICE_PID);
            if (pid == null) {
                pid = info.getServiceReference().getProperty(LegacyResourceProviderWhiteboard.ORIGINAL_SERVICE_PID);
            }
            this.pid = pid;
        }
    }
}
