/*
 * 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;
            this.updateHandlers();
        }
    }

    /**
     * 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;
                           if ( matchingHandlers.isEmpty() ) {
                               this.handlers.remove(info.getPath());
                           }
                       }
                   }
               }
           }

           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) {
            updateHandlers();
        }
        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();
        synchronized (this.handlers) {
            updateHandlers();
        }
        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 updateHandlers() {
        for (List<ResourceProviderHandler> list : handlers.values()) {
            if ( !list.isEmpty() ) {
                final ResourceProviderHandler h = list.get(0);
                if (h != null) {
                    updateProviderContext(h);
                    h.update();
                }
            }
        }
    }

    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;
        }
    }
}
