/*******************************************************************************
 * Copyright (c) 2011, 2015 VMware Inc. and others
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    SpringSource, a division of VMware - initial API and implementation and/or initial documentation
 *******************************************************************************/

package org.eclipse.equinox.internal.region;

import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicLong;
import org.eclipse.equinox.internal.region.hook.*;
import org.eclipse.equinox.region.*;
import org.osgi.framework.*;
import org.osgi.framework.hooks.bundle.*;
import org.osgi.framework.hooks.resolver.ResolverHookFactory;

/**
 * {@link StandardRegionDigraph} is the default implementation of {@link RegionDigraph}.
 * <p />
 * 
 * <strong>Concurrent Semantics</strong><br />
 * 
 * Thread safe.
 * 
 */
public final class StandardRegionDigraph implements BundleIdToRegionMapping, RegionDigraph {

	private static final Set<FilteredRegion> EMPTY_EDGE_SET = Collections.unmodifiableSet(new HashSet<FilteredRegion>());

	// This monitor guards the modifications and read operations on the digraph as well as 
	// bundle id modifications of all regions in this digraph
	private final Object monitor = new Object();

	private final Map<String, Region> regions = new HashMap<String, Region>();

	// Alien calls may be made to the following object while this.monitor is locked
	// as this.monitor is higher in the lock hierarchy than this object's own monitor.
	private final BundleIdToRegionMapping bundleIdToRegionMapping;

	/* edges maps a given region to an immutable set of edges with their tail at the given region. To update
	 * the edges for a region, the corresponding immutable set is replaced atomically. */
	private final Map<Region, Set<FilteredRegion>> edges = new HashMap<Region, Set<FilteredRegion>>();

	private final BundleContext bundleContext;

	private final ThreadLocal<Region> threadLocal;

	private final SubgraphTraverser subgraphTraverser;

	private final org.osgi.framework.hooks.bundle.CollisionHook bundleCollisionHook;
	private final org.osgi.framework.hooks.bundle.EventHook bundleEventHook;
	private final org.osgi.framework.hooks.bundle.FindHook bundleFindHook;
	@SuppressWarnings("deprecation")
	private final org.osgi.framework.hooks.service.EventHook serviceEventHook;
	private final org.osgi.framework.hooks.service.FindHook serviceFindHook;
	private final ResolverHookFactory resolverHookFactory;
	private final StandardRegionDigraph origin;
	// Guarded by the origin monitor
	private long originUpdateCount;
	private final AtomicLong updateCount = new AtomicLong();

	private volatile Region defaultRegion;

	public StandardRegionDigraph(StandardRegionDigraph origin) throws BundleException {
		this(null, null, origin);

	}

	public StandardRegionDigraph(BundleContext bundleContext, ThreadLocal<Region> threadLocal) throws BundleException {
		this(bundleContext, threadLocal, null);
	}

	private StandardRegionDigraph(BundleContext bundleContext, ThreadLocal<Region> threadLocal, StandardRegionDigraph origin) throws BundleException {
		this.subgraphTraverser = new SubgraphTraverser();
		this.bundleIdToRegionMapping = new StandardBundleIdToRegionMapping();
		this.bundleContext = bundleContext;
		this.threadLocal = threadLocal;

		// Note we are safely escaping this only because we know the hook impls
		// do not escape the digraph to other threads on construction.
		this.resolverHookFactory = new RegionResolverHookFactory(this);

		this.bundleFindHook = new RegionBundleFindHook(this, bundleContext == null ? 0 : bundleContext.getBundle().getBundleId());
		this.bundleEventHook = new RegionBundleEventHook(this, this.threadLocal, bundleContext == null ? 0 : bundleContext.getBundle().getBundleId());
		this.bundleCollisionHook = new RegionBundleCollisionHook(this, this.threadLocal);

		this.serviceFindHook = new RegionServiceFindHook(this);
		this.serviceEventHook = new RegionServiceEventHook(this);
		this.origin = origin;
		if (origin != null) {
			synchronized (origin.monitor) {
				this.originUpdateCount = origin.updateCount.get();
				this.replace(origin, false);
			}
		} else {
			this.originUpdateCount = -1;
		}
		this.defaultRegion = null;
	}

	/**
	 * {@inheritDoc}
	 */
	public Region createRegion(String regionName) throws BundleException {
		return createRegion(regionName, true);
	}

	private Region createRegion(String regionName, boolean notify) throws BundleException {
		Region region = new BundleIdBasedRegion(regionName, this, this, this.bundleContext, this.threadLocal);
		synchronized (this.monitor) {
			if (getRegion(regionName) != null) {
				throw new BundleException("Region '" + regionName + "' already exists", BundleException.UNSUPPORTED_OPERATION); //$NON-NLS-1$ //$NON-NLS-2$
			}
			this.regions.put(region.getName(), region);
			this.edges.put(region, EMPTY_EDGE_SET);
			incrementUpdateCount();
		}
		if (notify) {
			notifyAdded(region);
		}
		return region;
	}

	/**
	 * {@inheritDoc}
	 */
	public void connect(Region tailRegion, RegionFilter filter, Region headRegion) throws BundleException {
		createConnection(tailRegion, filter, headRegion, false);
	}

	/**
	 * {@inheritDoc}
	 */
	public RegionFilter replaceConnection(Region tailRegion, RegionFilter filter, Region headRegion) throws BundleException {
		return createConnection(tailRegion, filter, headRegion, true);
	}

	private RegionFilter createConnection(Region tailRegion, RegionFilter filter, Region headRegion, boolean replace) throws BundleException {
		if (tailRegion == null)
			throw new IllegalArgumentException("The tailRegion must not be null."); //$NON-NLS-1$
		if (!replace && filter == null)
			throw new IllegalArgumentException("The filter must not be null."); //$NON-NLS-1$
		if (headRegion == null)
			throw new IllegalArgumentException("The headRegion must not be null."); //$NON-NLS-1$
		if (headRegion.equals(tailRegion)) {
			throw new BundleException("Cannot connect region '" + headRegion + "' to itself", BundleException.UNSUPPORTED_OPERATION); //$NON-NLS-1$ //$NON-NLS-2$
		}
		if (tailRegion.getRegionDigraph() != this)
			throw new IllegalArgumentException("The tailRegion does not belong to this digraph."); //$NON-NLS-1$
		if (headRegion.getRegionDigraph() != this)
			throw new IllegalArgumentException("The headRegion does not belong to this digraph."); //$NON-NLS-1$

		FilteredRegion existing = null;
		boolean tailAdded = false;
		boolean headAdded = false;
		synchronized (this.monitor) {
			Set<FilteredRegion> connections = this.edges.get(tailRegion);
			if (connections == null) {
				connections = new HashSet<FilteredRegion>();
			} else {
				connections = new HashSet<FilteredRegion>(connections);
				for (FilteredRegion edge : connections) {
					if (headRegion.equals(edge.getRegion())) {
						if (replace) {
							existing = edge;
						} else {
							throw new BundleException("Region '" + tailRegion + "' is already connected to region '" + headRegion, BundleException.UNSUPPORTED_OPERATION); //$NON-NLS-1$ //$NON-NLS-2$
						}
					}
				}
			}

			checkFilterDoesNotAllowExistingBundle(tailRegion, filter);

			tailAdded = this.regions.put(tailRegion.getName(), tailRegion) == null;
			headAdded = this.regions.put(headRegion.getName(), headRegion) == null;

			if (existing != null) {
				connections.remove(existing);
			}

			if (filter != null) {
				connections.add(new StandardFilteredRegion(headRegion, filter));
			}

			this.edges.put(tailRegion, Collections.unmodifiableSet(connections));
			incrementUpdateCount();
		}
		if (tailAdded) {
			notifyAdded(tailRegion);
		}
		if (headAdded) {
			notifyAdded(headRegion);
		}
		return existing == null ? null : existing.getFilter();
	}

	private void checkFilterDoesNotAllowExistingBundle(Region tailRegion, RegionFilter filter) {
		// TODO: enumerate the bundles in the region and check the filter does not allow any of them
	}

	/**
	 * {@inheritDoc}
	 */
	public Iterator<Region> iterator() {
		synchronized (this.monitor) {
			Set<Region> snapshot = new HashSet<Region>(this.regions.size());
			snapshot.addAll(this.regions.values());
			return snapshot.iterator();
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public Set<FilteredRegion> getEdges(Region tailRegion) {
		synchronized (this.monitor) {
			// Cope with the case where tailRegion is not in the digraph
			Set<FilteredRegion> edgeSet = this.edges.get(tailRegion);
			return edgeSet == null ? EMPTY_EDGE_SET : edgeSet;
		}
	}

	static class StandardFilteredRegion implements FilteredRegion {

		private Region region;

		private RegionFilter regionFilter;

		StandardFilteredRegion(Region region, RegionFilter regionFilter) {
			this.region = region;
			this.regionFilter = regionFilter;
		}

		public Region getRegion() {
			return this.region;
		}

		public RegionFilter getFilter() {
			return this.regionFilter;
		}

	}

	/**
	 * {@inheritDoc}
	 */
	public Region getRegion(String regionName) {
		synchronized (this.monitor) {
			return regions.get(regionName);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public Region getRegion(Bundle bundle) {
		return getRegion(bundle.getBundleId());
	}

	/**
	 * {@inheritDoc}
	 */
	public Region getRegion(long bundleId) {
		synchronized (this.monitor) {
			return this.bundleIdToRegionMapping.getRegion(bundleId);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public void removeRegion(Region region) {
		if (region == null)
			throw new IllegalArgumentException("The region cannot be null."); //$NON-NLS-1$
		notifyRemoving(region);
		synchronized (this.monitor) {
			if (this.defaultRegion != null && this.defaultRegion.equals(region)) {
				this.defaultRegion = null;
			}
			this.regions.remove(region.getName());
			this.edges.remove(region);
			for (Entry<Region, Set<FilteredRegion>> entry : edges.entrySet()) {
				Region r = entry.getKey();
				Set<FilteredRegion> edgeSet = entry.getValue();
				for (FilteredRegion edge : edgeSet) {
					if (region.equals(edge.getRegion())) {
						Set<FilteredRegion> mutableEdgeSet = new HashSet<FilteredRegion>(edgeSet);
						mutableEdgeSet.remove(edge);
						this.edges.put(r, Collections.unmodifiableSet(mutableEdgeSet));
						break;
					}
				}
			}
			this.bundleIdToRegionMapping.dissociateRegion(region);
			incrementUpdateCount();
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public String toString() {
		synchronized (this.monitor) {
			StringBuffer s = new StringBuffer();
			boolean first = true;
			s.append("RegionDigraph{"); //$NON-NLS-1$
			for (Region r : this) {
				if (!first) {
					s.append(", "); //$NON-NLS-1$
				}
				s.append(r);
				first = false;
			}
			s.append("}"); //$NON-NLS-1$

			s.append("["); //$NON-NLS-1$
			first = true;
			for (Region r : this) {
				Set<FilteredRegion> edgeSet = this.edges.get(r);
				if (edgeSet != null) {
					for (FilteredRegion filteredRegion : edgeSet) {
						if (!first) {
							s.append(", "); //$NON-NLS-1$
						}
						s.append(r + "->" + filteredRegion.getRegion()); //$NON-NLS-1$
						first = false;
					}
				}
			}
			s.append("]"); //$NON-NLS-1$
			return s.toString();
		}
	}

	public Set<Region> getRegions() {
		Set<Region> result = new HashSet<Region>();
		synchronized (this.monitor) {
			result.addAll(this.regions.values());
		}
		return result;
	}

	public RegionFilterBuilder createRegionFilterBuilder() {
		return new StandardRegionFilterBuilder();
	}

	private void notifyAdded(Region region) {
		Set<RegionLifecycleListener> listeners = getListeners();
		for (RegionLifecycleListener listener : listeners) {
			listener.regionAdded(region);
		}
	}

	private void notifyRemoving(Region region) {
		Set<RegionLifecycleListener> listeners = getListeners();
		for (RegionLifecycleListener listener : listeners) {
			listener.regionRemoving(region);
		}
	}

	private Set<RegionLifecycleListener> getListeners() {
		if (this.bundleContext == null)
			return Collections.emptySet();
		Set<RegionLifecycleListener> listeners = new HashSet<RegionLifecycleListener>();
		try {
			Collection<ServiceReference<RegionLifecycleListener>> listenerServiceReferences = this.bundleContext.getServiceReferences(RegionLifecycleListener.class, null);
			for (ServiceReference<RegionLifecycleListener> listenerServiceReference : listenerServiceReferences) {
				RegionLifecycleListener regionLifecycleListener = this.bundleContext.getService(listenerServiceReference);
				if (regionLifecycleListener != null) {
					listeners.add(regionLifecycleListener);
				}
			}
		} catch (InvalidSyntaxException e) {
			e.printStackTrace();
		}
		return listeners;
	}

	/**
	 * {@inheritDoc}
	 */
	public void visitSubgraph(Region startingRegion, RegionDigraphVisitor visitor) {
		this.subgraphTraverser.visitSubgraph(startingRegion, visitor);
	}

	/**
	 * Returns a snapshot of filtered regions
	 * 
	 * @return a snapshot of filtered regions
	 */
	Map<Region, Set<FilteredRegion>> getFilteredRegions() {
		synchronized (this.monitor) {
			return new HashMap<Region, Set<FilteredRegion>>(this.edges);
		}
	}

	/** 
	 * {@inheritDoc}
	 */
	public RegionDigraphPersistence getRegionDigraphPersistence() {
		return new StandardRegionDigraphPersistence();
	}

	/** 
	 * {@inheritDoc}
	 */
	@Override
	public RegionDigraph copy() throws BundleException {
		return new StandardRegionDigraph(this);
	}

	/** 
	 * {@inheritDoc}
	 */
	@Override
	public void replace(RegionDigraph digraph) throws BundleException {
		replace(digraph, true);
	}

	private void replace(RegionDigraph digraph, boolean check) throws BundleException {
		if (!(digraph instanceof StandardRegionDigraph))
			throw new IllegalArgumentException("Only digraphs of type '" + StandardRegionDigraph.class.getName() + "' are allowed: " + digraph.getClass().getName()); //$NON-NLS-1$ //$NON-NLS-2$
		StandardRegionDigraph replacement = (StandardRegionDigraph) digraph;
		if (check && replacement.origin != this)
			throw new IllegalArgumentException("The replacement digraph is not a copy of this digraph."); //$NON-NLS-1$

		// notify removing first, and outside the monitor lock
		final Set<Region> removed = getRegions();
		removed.removeAll(replacement.getRegions());
		for (Region region : removed) {
			notifyRemoving(region);
		}

		Map<Region, Set<FilteredRegion>> filteredRegions = replacement.getFilteredRegions();
		final Set<Region> added = new HashSet<Region>();
		synchronized (this.monitor) {
			if (check && this.updateCount.get() != replacement.originUpdateCount) {
				throw new BundleException("The origin update count has changed since the replacement copy was created.", BundleException.INVALID_OPERATION); //$NON-NLS-1$
			}
			Map<String, Region> nameToRegion = new HashMap<String, Region>(regions);
			this.regions.clear();
			this.edges.clear();
			this.bundleIdToRegionMapping.clear();
			for (Region original : filteredRegions.keySet()) {
				Region copy = nameToRegion.get(original.getName());
				if (copy != null) {
					// reuse the previous region object
					regions.put(copy.getName(), copy);
					edges.put(copy, EMPTY_EDGE_SET);
				} else {
					// create a new one
					copy = this.createRegion(original.getName(), false);
					// collect added for notifying later ouside the lock
					added.add(copy);
				}
				for (Long id : original.getBundleIds()) {
					copy.addBundle(id);
				}
			}
			for (Map.Entry<Region, Set<FilteredRegion>> connection : filteredRegions.entrySet()) {
				Region tailRegion = this.getRegion(connection.getKey().getName());
				for (FilteredRegion headFilter : connection.getValue()) {
					Region headRegion = this.getRegion(headFilter.getRegion().getName());
					this.connect(tailRegion, headFilter.getFilter(), headRegion);
				}
			}
			incrementUpdateCount();
			if (check) {
				replacement.originUpdateCount = this.updateCount.get();
			}
		}
		// Now notify of additions outside the lock
		for (Region region : added) {
			notifyAdded(region);
		}
	}

	/** 
	 * {@inheritDoc}
	 */
	@Override
	public ResolverHookFactory getResolverHookFactory() {
		return resolverHookFactory;
	}

	CollisionHook getBundleCollisionHook() {
		return bundleCollisionHook;
	}

	/** 
	 * {@inheritDoc}
	 */
	@Override
	public EventHook getBundleEventHook() {
		return bundleEventHook;
	}

	/** 
	 * {@inheritDoc}
	 */
	@Override
	public FindHook getBundleFindHook() {
		return bundleFindHook;
	}

	/** 
	 * {@inheritDoc}
	 */
	@SuppressWarnings("deprecation")
	@Override
	public org.osgi.framework.hooks.service.EventHook getServiceEventHook() {
		return serviceEventHook;
	}

	/** 
	 * {@inheritDoc}
	 */
	@Override
	public org.osgi.framework.hooks.service.FindHook getServiceFindHook() {
		return serviceFindHook;
	}

	/** 
	 * {@inheritDoc}
	 */
	@Override
	public void setDefaultRegion(Region defaultRegion) {
		synchronized (this.monitor) {
			if (defaultRegion != null) {
				checkRegionExists(defaultRegion);
			}
			this.defaultRegion = defaultRegion;
		}
	}

	/** 
	 * {@inheritDoc}
	 */
	@Override
	public Region getDefaultRegion() {
		return this.defaultRegion;
	}

	/** 
	 * {@inheritDoc}
	 */
	@Override
	public void associateBundleWithRegion(long bundleId, Region region) throws BundleException {
		synchronized (this.monitor) {
			checkRegionExists(region);
			this.bundleIdToRegionMapping.associateBundleWithRegion(bundleId, region);
			incrementUpdateCount();
		}
	}

	private void checkRegionExists(Region region) {
		if (this.regions.get(region.getName()) == null) {
			throw new IllegalStateException("Operation not allowed on region " + region.getName() + " which is not part of a digraph"); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	private void incrementUpdateCount() {
		synchronized (this.monitor) {
			this.updateCount.incrementAndGet();
		}

	}

	/** 
	 * {@inheritDoc}
	 */
	@Override
	public void dissociateBundleFromRegion(long bundleId, Region region) {
		synchronized (this.monitor) {
			checkRegionExists(region);
			this.bundleIdToRegionMapping.dissociateBundleFromRegion(bundleId, region);
			incrementUpdateCount();
		}
	}

	/** 
	 * {@inheritDoc}
	 */
	@Override
	public boolean isBundleAssociatedWithRegion(long bundleId, Region region) {
		synchronized (this.monitor) {
			return this.bundleIdToRegionMapping.isBundleAssociatedWithRegion(bundleId, region);
		}
	}

	/** 
	 * {@inheritDoc}
	 */
	@Override
	public Set<Long> getBundleIds(Region region) {
		synchronized (this.monitor) {
			return this.bundleIdToRegionMapping.getBundleIds(region);
		}
	}

	/** 
	 * {@inheritDoc}
	 */
	@Override
	public void clear() {
		synchronized (this.monitor) {
			this.bundleIdToRegionMapping.clear();
			incrementUpdateCount();
		}
	}

	/** 
	 * {@inheritDoc}
	 */
	@Override
	public void dissociateRegion(Region region) {
		synchronized (this.monitor) {
			this.bundleIdToRegionMapping.dissociateRegion(region);
			incrementUpdateCount();
		}
	}

}
