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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.discovery.ClusterView;
import org.apache.sling.discovery.DiscoveryService;
import org.apache.sling.discovery.InstanceDescription;
import org.apache.sling.discovery.InstanceFilter;
import org.apache.sling.discovery.PropertyProvider;
import org.apache.sling.discovery.TopologyEvent;
import org.apache.sling.discovery.TopologyEvent.Type;
import org.apache.sling.discovery.TopologyEventListener;
import org.apache.sling.discovery.TopologyView;
import org.apache.sling.settings.SlingSettingsService;
import org.osgi.framework.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This is a simple implementation of the discovery service
 * which can be used for a cluster less installation (= single instance).
 * It is disabled by default and can be enabled through a OSGi configuration.
 */
@Component(policy = ConfigurationPolicy.REQUIRE, immediate=true)
@Service(value = {DiscoveryService.class})
public class NoClusterDiscoveryService implements DiscoveryService {

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

    /**
     * Sling settings service to get the Sling ID and run modes.
     */
    @Reference
    private SlingSettingsService settingsService;

    /**
     * All topology event listeners.
     */
    @Reference(cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC)
    private TopologyEventListener[] listeners = new TopologyEventListener[0];

    /**
     * All property providers.
     */
    @Reference(cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC,
               referenceInterface=PropertyProvider.class, updated="updatedPropertyProvider")
    private List<ProviderInfo> providerInfos = new ArrayList<ProviderInfo>();

    /**
     * Special lock object to sync data structure access
     */
    private final Object lock = new Object();

    /**
     * The current topology view.
     */
    private TopologyView topologyView;

    private Map<String, String> cachedProperties = new HashMap<String, String>();

    /**
     * Activate this service
     * Create a new description.
     */
    @Activate
    protected void activate() {
        logger.debug("NoClusterDiscoveryService started.");
        final InstanceDescription myDescription = new InstanceDescription() {

            public boolean isLocal() {
                return true;
            }

            public boolean isLeader() {
                return true;
            }

            public String getSlingId() {
                return settingsService.getSlingId();
            }

            public String getProperty(final String name) {
            	synchronized(lock) {
            		return cachedProperties.get(name);
            	}
            }

			public Map<String, String> getProperties() {
				synchronized(lock) {
					return Collections.unmodifiableMap(cachedProperties);
				}
			}

			public ClusterView getClusterView() {
				final Collection<ClusterView> clusters = topologyView.getClusterViews();
				if (clusters==null || clusters.size()==0) {
					return null;
				}
				return clusters.iterator().next();
			}
        };
        final Set<InstanceDescription> instances = new HashSet<InstanceDescription>();
        instances.add(myDescription);

        final TopologyEventListener[] registeredServices;
		synchronized ( lock ) {
            registeredServices = this.listeners;
            final ClusterView clusterView = new ClusterView() {

                public InstanceDescription getLeader() {
                    return myDescription;
                }

                public List<InstanceDescription> getInstances() {
                    return new LinkedList<InstanceDescription>(instances);
                }

				public String getId() {
					return "0";
				}
            };
            this.topologyView = new TopologyView() {

    			public InstanceDescription getLocalInstance() {
    				return myDescription;
    			}

    			public boolean isCurrent() {
    				return true;
    			}

    			public Set<InstanceDescription> getInstances() {
    				return instances;
    			}

    			public Set<InstanceDescription> findInstances(InstanceFilter picker) {
    				Set<InstanceDescription> result = new HashSet<InstanceDescription>();
    				for (Iterator<InstanceDescription> it = getTopology().getInstances().iterator(); it.hasNext();) {
    					InstanceDescription instance = it.next();
    					if (picker.accept(instance)) {
    						result.add(instance);
    					}
    				}
    				return result;
    			}

    			public Set<ClusterView> getClusterViews() {
    				Set<ClusterView> clusters = new HashSet<ClusterView>();
    				clusters.add(clusterView);
    				return clusters;
    			}

    		};
        }
        for(final TopologyEventListener da: registeredServices) {
        	da.handleTopologyEvent(new TopologyEvent(Type.TOPOLOGY_INIT, null, topologyView));
        }
    }

    /**
     * Deactivate this service.
     */
    @Deactivate
    protected void deactivate() {
        logger.debug("NoClusterDiscoveryService stopped.");
        this.topologyView = null;
    }

    /**
     * Bind a new property provider.
     */
    @SuppressWarnings("unused")
	private void bindPropertyProvider(final PropertyProvider propertyProvider, final Map<String, Object> props) {
    	logger.debug("bindPropertyProvider: Binding PropertyProvider {}", propertyProvider);

        final TopologyEventListener[] awares;
        synchronized (lock) {
            final ProviderInfo info = new ProviderInfo(propertyProvider, props);
            this.providerInfos.add(info);
            Collections.sort(this.providerInfos);
            this.updatePropertiesCache();
            if ( this.topologyView == null ) {
                awares = null;
            } else {
                awares = this.listeners;
            }
        }
        if ( awares != null ) {
            for(final TopologyEventListener da : awares) {
                da.handleTopologyEvent(new TopologyEvent(Type.PROPERTIES_CHANGED, this.topologyView, this.topologyView));
            }
        }
    }

    /**
     * Update a property provider.
     */
    @SuppressWarnings("unused")
    private void updatedPropertyProvider(final PropertyProvider propertyProvider, final Map<String, Object> props) {
        logger.debug("bindPropertyProvider: Updating PropertyProvider {}", propertyProvider);

        this.unbindPropertyProvider(propertyProvider, props, false);
        this.bindPropertyProvider(propertyProvider, props);
    }

    /**
     * Unbind a property provider
     */
    @SuppressWarnings("unused")
	private void unbindPropertyProvider(final PropertyProvider propertyProvider, final Map<String, Object> props) {
        this.unbindPropertyProvider(propertyProvider, props, true);
    }

    /**
     * Unbind a property provider
     */
    @SuppressWarnings("unused")
    private void unbindPropertyProvider(final PropertyProvider propertyProvider,
            final Map<String, Object> props,
            final boolean inform) {
    	logger.debug("unbindPropertyProvider: Releasing PropertyProvider {}", propertyProvider);

    	final TopologyEventListener[] awares;
        synchronized (lock) {
            final ProviderInfo info = new ProviderInfo(propertyProvider, props);
            this.providerInfos.remove(info);
            this.updatePropertiesCache();
            if ( this.topologyView == null ) {
                awares = null;
            } else {
                awares = this.listeners;
            }
        }
        if ( inform && awares != null ) {
            for(final TopologyEventListener da : awares) {
                da.handleTopologyEvent(new TopologyEvent(Type.PROPERTIES_CHANGED, this.topologyView, this.topologyView));
            }
        }
    }

    private void updatePropertiesCache() {
        final Map<String, String> newProps = new HashMap<String, String>();
        for(final ProviderInfo info : this.providerInfos) {
            newProps.putAll(info.properties);
        }
        this.cachedProperties = newProps;
        if ( this.logger.isDebugEnabled() ) {
            this.logger.debug("New properties: {}", this.cachedProperties);
        }
    }

    @SuppressWarnings("unused")
    private void bindTopologyEventListener(final TopologyEventListener clusterAware) {

        logger.debug("bindTopologyEventListener: Binding TopologyEventListener {}", clusterAware);

        boolean inform = true;
        synchronized (lock) {
            List<TopologyEventListener> currentList = new ArrayList<TopologyEventListener>(
                Arrays.asList(listeners));
            currentList.add(clusterAware);
            this.listeners = currentList.toArray(new TopologyEventListener[currentList.size()]);
            if ( this.topologyView == null ) {
                inform = false;
            }
        }

        if ( inform ) {
        	clusterAware.handleTopologyEvent(new TopologyEvent(Type.TOPOLOGY_INIT, null, topologyView));
        }
    }

    @SuppressWarnings("unused")
    private void unbindTopologyEventListener(final TopologyEventListener clusterAware) {

        logger.debug("unbindTopologyEventListener: Releasing TopologyEventListener {}", clusterAware);

        synchronized (lock) {
            List<TopologyEventListener> currentList = new ArrayList<TopologyEventListener>(
                Arrays.asList(listeners));
            currentList.remove(clusterAware);
            this.listeners = currentList.toArray(new TopologyEventListener[currentList.size()]);
        }
    }

    /**
     * @see DiscoveryService#getTopology()
     */
    public TopologyView getTopology() {
    	return topologyView;
    }

    /**
     * Internal class caching some provider infos like service id and ranking.
     */
    private final static class ProviderInfo implements Comparable<ProviderInfo> {

        public final PropertyProvider provider;
        public final int ranking;
        public final long serviceId;
        public final Map<String, String> properties = new HashMap<String, String>();

        public ProviderInfo(final PropertyProvider provider, final Map<String, Object> serviceProps) {
            this.provider = provider;
            final Object sr = serviceProps.get(Constants.SERVICE_RANKING);
            if ( sr == null || !(sr instanceof Integer)) {
                this.ranking = 0;
            } else {
                this.ranking = (Integer)sr;
            }
            this.serviceId = (Long)serviceProps.get(Constants.SERVICE_ID);
            final Object namesObj = serviceProps.get(PropertyProvider.PROPERTY_PROPERTIES);
            if ( namesObj instanceof String ) {
                final String val = provider.getProperty((String)namesObj);
                if ( val != null ) {
                    this.properties.put((String)namesObj, val);
                }
            } else if ( namesObj instanceof String[] ) {
                for(final String name : (String[])namesObj ) {
                    final String val = provider.getProperty(name);
                    if ( val != null ) {
                        this.properties.put(name, val);
                    }
                }
            }
        }

        /**
         * @see java.lang.Comparable#compareTo(java.lang.Object)
         */
        public int compareTo(final ProviderInfo o) {
            // Sort by rank in ascending order.
            if ( this.ranking < o.ranking ) {
                return -1; // lower rank
            } else if (this.ranking > o.ranking ) {
                return 1; // higher rank
            }
            // If ranks are equal, then sort by service id in descending order.
            return (this.serviceId < o.serviceId) ? 1 : -1;
        }

        @Override
        public boolean equals(final Object obj) {
            if ( obj instanceof ProviderInfo ) {
                return ((ProviderInfo)obj).serviceId == this.serviceId;
            }
            return false;
        }

        @Override
        public int hashCode() {
            return provider.hashCode();
        }
    }
}
