/*******************************************************************************
 * Copyright (c) 2003, 2006 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.osgi.internal.resolver;

import java.util.*;

import org.eclipse.osgi.framework.adaptor.core.StateManager;
import org.eclipse.osgi.framework.debug.Debug;
import org.eclipse.osgi.framework.debug.FrameworkDebugOptions;
import org.eclipse.osgi.framework.internal.core.*;
import org.eclipse.osgi.service.resolver.*;
import org.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.BundleException;
import org.osgi.framework.Version;

public abstract class StateImpl implements State {
	public static final String[] PROPS = {"osgi.os", "osgi.ws", "osgi.nl", "osgi.arch", Constants.OSGI_FRAMEWORK_SYSTEM_PACKAGES, Constants.OSGI_RESOLVER_MODE}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ 

	transient private Resolver resolver;
	transient private StateDeltaImpl changes;
	transient private boolean resolving = false;
	transient private HashSet removalPendings = new HashSet();
	private boolean resolved = true;
	private long timeStamp = System.currentTimeMillis();
	private KeyedHashSet bundleDescriptions = new KeyedHashSet(false);
	private StateObjectFactory factory;
	private KeyedHashSet resolvedBundles = new KeyedHashSet();
	boolean fullyLoaded = false;
	private boolean dynamicCacheChanged = false;
	// only used for lazy loading of BundleDescriptions
	private StateReader reader;
	private Dictionary[] platformProperties = {new Hashtable(PROPS.length)}; // Dictionary here because of Filter API
	private ExportPackageDescription[] systemExports = new ExportPackageDescription[0];

	private static long cumulativeTime;

	protected StateImpl() {
		// to prevent extra-package instantiation 
	}

	public boolean addBundle(BundleDescription description) {
		if (!basicAddBundle(description))
			return false;
		resolved = false;
		getDelta().recordBundleAdded((BundleDescriptionImpl) description);
		if (resolver != null)
			resolver.bundleAdded(description);
		return true;
	}

	public boolean updateBundle(BundleDescription newDescription) {
		BundleDescriptionImpl existing = (BundleDescriptionImpl) bundleDescriptions.get((BundleDescriptionImpl) newDescription);
		if (existing == null)
			return false;
		if (!bundleDescriptions.remove(existing))
			return false;
		resolvedBundles.remove(existing);
		if (!basicAddBundle(newDescription))
			return false;
		resolved = false;
		getDelta().recordBundleUpdated((BundleDescriptionImpl) newDescription);
		if (resolver != null) {
			boolean pending = existing.getDependents().length > 0;
			resolver.bundleUpdated(newDescription, existing, pending);
			if (pending) {
				getDelta().recordBundleRemovalPending(existing);
				removalPendings.add(existing);
			} else {
				// an existing bundle has been updated with no dependents it can safely be unresolved now
				synchronized (this) {
					try {
						resolving = true;
						resolveBundle(existing, false, null, null, null, null);
					} finally {
						resolving = false;
					}
				}
			}
		}
		return true;
	}

	public BundleDescription removeBundle(long bundleId) {
		BundleDescription toRemove = getBundle(bundleId);
		if (toRemove == null || !removeBundle(toRemove))
			return null;
		return toRemove;
	}

	public boolean removeBundle(BundleDescription toRemove) {
		if (!bundleDescriptions.remove((KeyedElement) toRemove))
			return false;
		resolvedBundles.remove((KeyedElement) toRemove);
		resolved = false;
		getDelta().recordBundleRemoved((BundleDescriptionImpl) toRemove);
		if (resolver != null) {
			boolean pending = toRemove.getDependents().length > 0;
			resolver.bundleRemoved(toRemove, pending);
			if (pending) {
				getDelta().recordBundleRemovalPending((BundleDescriptionImpl) toRemove);
				removalPendings.add(toRemove);
			} else {
				// a bundle has been removed with no dependents it can safely be unresolved now
				synchronized (this) {
					try {
						resolving = true;
						resolveBundle(toRemove, false, null, null, null, null);
					} finally {
						resolving = false;
					}
				}
			}
		}
		return true;
	}

	public StateDelta getChanges() {
		return getDelta();
	}

	private StateDeltaImpl getDelta() {
		if (changes == null)
			changes = new StateDeltaImpl(this);
		return changes;
	}

	public BundleDescription[] getBundles(final String symbolicName) {
		final List bundles = new ArrayList();
		for (Iterator iter = bundleDescriptions.iterator(); iter.hasNext();) {
			BundleDescription bundle = (BundleDescription) iter.next();
			if (symbolicName.equals(bundle.getSymbolicName()))
				bundles.add(bundle);
		}
		return (BundleDescription[]) bundles.toArray(new BundleDescription[bundles.size()]);
	}

	public BundleDescription[] getBundles() {
		return (BundleDescription[]) bundleDescriptions.elements(new BundleDescription[bundleDescriptions.size()]);
	}

	public BundleDescription getBundle(long id) {
		BundleDescription result = (BundleDescription) bundleDescriptions.getByKey(new Long(id));
		if (result != null)
			return result;
		// need to look in removal pending bundles;
		for (Iterator iter = removalPendings.iterator(); iter.hasNext();) {
			BundleDescription removedBundle = (BundleDescription) iter.next();
			if (removedBundle.getBundleId() == id) // just return the first matching id
				return removedBundle;
		}
		return null;
	}

	public BundleDescription getBundle(String name, Version version) {
		BundleDescription[] allBundles = getBundles(name);
		if (allBundles.length == 1)
			return version == null || allBundles[0].getVersion().equals(version) ? allBundles[0] : null;

		if (allBundles.length == 0)
			return null;

		BundleDescription unresolvedFound = null;
		BundleDescription resolvedFound = null;
		for (int i = 0; i < allBundles.length; i++) {
			BundleDescription current = allBundles[i];
			BundleDescription base;

			if (current.isResolved())
				base = resolvedFound;
			else
				base = unresolvedFound;

			if (version == null || current.getVersion().equals(version)) {
				if (base != null && (base.getVersion().compareTo(current.getVersion()) <= 0 || base.getBundleId() > current.getBundleId())) {
					if (base == resolvedFound)
						resolvedFound = current;
					else
						unresolvedFound = current;
				} else {
					if (current.isResolved())
						resolvedFound = current;
					else
						unresolvedFound = current;
				}

			}
		}
		if (resolvedFound != null)
			return resolvedFound;

		return unresolvedFound;
	}

	public long getTimeStamp() {
		return timeStamp;
	}

	public boolean isResolved() {
		return resolved || isEmpty();
	}

	public void resolveConstraint(VersionConstraint constraint, BaseDescription supplier) {
		((VersionConstraintImpl) constraint).setSupplier(supplier);
	}

	public void resolveBundle(BundleDescription bundle, boolean status, BundleDescription[] hosts, ExportPackageDescription[] selectedExports, BundleDescription[] resolvedRequires, ExportPackageDescription[] resolvedImports) {
		if (!resolving)
			throw new IllegalStateException(); // TODO need error message here!
		BundleDescriptionImpl modifiable = (BundleDescriptionImpl) bundle;
		// must record the change before setting the resolve state to 
		// accurately record if a change has happened.
		getDelta().recordBundleResolved(modifiable, status);
		// force the new resolution data to stay in memory; we will not read this from disk anymore
		modifiable.setLazyLoaded(false);
		modifiable.setStateBit(BundleDescriptionImpl.RESOLVED, status);
		if (status) {
			resolveConstraints(modifiable, hosts, selectedExports, resolvedRequires, resolvedImports);
			resolvedBundles.add(modifiable);
		} else {
			// ensures no links are left 
			unresolveConstraints(modifiable);
			// remove the bundle from the resolved pool
			resolvedBundles.remove(modifiable);
		}
	}

	public void removeBundleComplete(BundleDescription bundle) {
		if (!resolving)
			throw new IllegalStateException(); // TODO need error message here!
		getDelta().recordBundleRemovalComplete((BundleDescriptionImpl) bundle);
		removalPendings.remove(bundle);
	}

	private void resolveConstraints(BundleDescriptionImpl bundle, BundleDescription[] hosts, ExportPackageDescription[] selectedExports, BundleDescription[] resolvedRequires, ExportPackageDescription[] resolvedImports) {
		HostSpecificationImpl hostSpec = (HostSpecificationImpl) bundle.getHost();
		if (hostSpec != null) {
			if (hosts != null) {
				hostSpec.setHosts(hosts);
				for (int i = 0; i < hosts.length; i++)
					((BundleDescriptionImpl) hosts[i]).addDependency(bundle);
			}
		}

		bundle.setSelectedExports(selectedExports);
		bundle.setResolvedRequires(resolvedRequires);
		bundle.setResolvedImports(resolvedImports);

		bundle.addDependencies(hosts);
		bundle.addDependencies(resolvedRequires);
		bundle.addDependencies(resolvedImports);
	}

	private void unresolveConstraints(BundleDescriptionImpl bundle) {
		HostSpecificationImpl host = (HostSpecificationImpl) bundle.getHost();
		if (host != null)
			host.setHosts(null);

		bundle.setSelectedExports(null);
		bundle.setResolvedImports(null);
		bundle.setResolvedRequires(null);

		bundle.removeDependencies();
	}

	private synchronized StateDelta resolve(boolean incremental, BundleDescription[] reResolve) {
		try {
			resolving = true;
			if (resolver == null)
				throw new IllegalStateException("no resolver set"); //$NON-NLS-1$
			fullyLoad();
			long start = 0;
			if (StateManager.DEBUG_PLATFORM_ADMIN_RESOLVER)
				start = System.currentTimeMillis();
			if (!incremental) {
				resolved = false;
				reResolve = getBundles();
				// need to get any removal pendings before flushing
				if (removalPendings.size() > 0) {
					BundleDescription[] removed = getRemovalPendings();
					reResolve = mergeBundles(reResolve, removed);
				}
				flush(reResolve);
			}
			if (resolved && reResolve == null)
				return new StateDeltaImpl(this);
			if (removalPendings.size() > 0) {
				BundleDescription[] removed = getRemovalPendings();
				reResolve = mergeBundles(reResolve, removed);
			}
			resolver.resolve(reResolve, platformProperties);
			resolved = true;

			StateDelta savedChanges = changes == null ? new StateDeltaImpl(this) : changes;
			changes = new StateDeltaImpl(this);

			if (StateManager.DEBUG_PLATFORM_ADMIN_RESOLVER) {
				long time = System.currentTimeMillis() - start;
				Debug.println("Time spent resolving: " + time); //$NON-NLS-1$
				cumulativeTime = cumulativeTime + time;
				FrameworkDebugOptions.getDefault().setOption("org.eclipse.core.runtime.adaptor/resolver/timing/value", Long.toString(cumulativeTime)); //$NON-NLS-1$
			}

			return savedChanges;
		} finally {
			resolving = false;
		}
	}

	private BundleDescription[] mergeBundles(BundleDescription[] reResolve, BundleDescription[] removed) {
		if (reResolve == null)
			return removed; // just return all the removed bundles
		if (reResolve.length == 0)
			return reResolve; // if reResolve length==0 then we want to prevent pending removal
		// merge in all removal pending bundles that are not already in the list
		ArrayList result = new ArrayList(reResolve.length + removed.length);
		for (int i = 0; i < reResolve.length; i++)
			result.add(reResolve[i]);
		for (int i = 0; i < removed.length; i++) {
			boolean found = false;
			for (int j = 0; j < reResolve.length; j++) {
				if (removed[i] == reResolve[j]) {
					found = true;
					break;
				}
			}
			if (!found)
				result.add(removed[i]);
		}
		return (BundleDescription[]) result.toArray(new BundleDescription[result.size()]);
	}

	private void flush(BundleDescription[] bundles) {
		resolver.flush();
		resolved = false;
		if (resolvedBundles.isEmpty())
			return;
		for (int i = 0; i < bundles.length; i++) {
			resolveBundle(bundles[i], false, null, null, null, null);
		}
		resolvedBundles.clear();
	}

	public StateDelta resolve() {
		return resolve(true, null);
	}

	public StateDelta resolve(boolean incremental) {
		return resolve(incremental, null);
	}

	public StateDelta resolve(BundleDescription[] reResolve) {
		return resolve(true, reResolve);
	}

	public void setOverrides(Object value) {
		throw new UnsupportedOperationException();
	}

	public BundleDescription[] getResolvedBundles() {
		return (BundleDescription[]) resolvedBundles.elements(new BundleDescription[resolvedBundles.size()]);
	}

	public boolean isEmpty() {
		return bundleDescriptions.isEmpty();
	}

	void setResolved(boolean resolved) {
		this.resolved = resolved;
	}

	boolean basicAddBundle(BundleDescription description) {
		((BundleDescriptionImpl) description).setContainingState(this);
		return bundleDescriptions.add((BundleDescriptionImpl) description);
	}

	void addResolvedBundle(BundleDescriptionImpl resolvedBundle) {
		resolvedBundles.add(resolvedBundle);
	}

	public ExportPackageDescription[] getExportedPackages() {
		fullyLoad();
		final List allExportedPackages = new ArrayList();
		for (Iterator iter = resolvedBundles.iterator(); iter.hasNext();) {
			BundleDescription bundle = (BundleDescription) iter.next();
			ExportPackageDescription[] bundlePackages = bundle.getSelectedExports();
			if (bundlePackages == null)
				continue;
			for (int i = 0; i < bundlePackages.length; i++)
				allExportedPackages.add(bundlePackages[i]);
		}
		for (Iterator iter = removalPendings.iterator(); iter.hasNext();) {
			BundleDescription bundle = (BundleDescription) iter.next();
			ExportPackageDescription[] bundlePackages = bundle.getSelectedExports();
			if (bundlePackages == null)
				continue;
			for (int i = 0; i < bundlePackages.length; i++)
				allExportedPackages.add(bundlePackages[i]);
		}
		return (ExportPackageDescription[]) allExportedPackages.toArray(new ExportPackageDescription[allExportedPackages.size()]);
	}

	BundleDescription[] getFragments(final BundleDescription host) {
		final List fragments = new ArrayList();
		for (Iterator iter = bundleDescriptions.iterator(); iter.hasNext();) {
			BundleDescription bundle = (BundleDescription) iter.next();
			HostSpecification hostSpec = bundle.getHost();

			if (hostSpec != null) {
				BundleDescription[] hosts = hostSpec.getHosts();
				if (hosts != null)
					for (int i = 0; i < hosts.length; i++)
						if (hosts[i] == host) {
							fragments.add(bundle);
							break;
						}
			}
		}
		return (BundleDescription[]) fragments.toArray(new BundleDescription[fragments.size()]);
	}

	public void setTimeStamp(long newTimeStamp) {
		timeStamp = newTimeStamp;
	}

	public StateObjectFactory getFactory() {
		return factory;
	}

	void setFactory(StateObjectFactory factory) {
		this.factory = factory;
	}

	public BundleDescription getBundleByLocation(String location) {
		for (Iterator i = bundleDescriptions.iterator(); i.hasNext();) {
			BundleDescription current = (BundleDescription) i.next();
			if (location.equals(current.getLocation()))
				return current;
		}
		return null;
	}

	public Resolver getResolver() {
		return resolver;
	}

	public void setResolver(Resolver newResolver) {
		if (resolver == newResolver)
			return;
		if (resolver != null) {
			Resolver oldResolver = resolver;
			resolver = null;
			oldResolver.setState(null);
		}
		resolver = newResolver;
		if (resolver == null)
			return;
		resolver.setState(this);
	}

	public synchronized boolean setPlatformProperties(Dictionary platformProperties) {
		if (this.platformProperties.length != 1)
			this.platformProperties = new Dictionary[] {new Hashtable(PROPS.length)};
		return setProps(this.platformProperties[0], platformProperties);
	}

	public boolean setPlatformProperties(Dictionary[] platformProperties) {
		if (platformProperties.length == 0)
			throw new IllegalArgumentException();
		if (this.platformProperties.length != platformProperties.length) {
			this.platformProperties = new Dictionary[platformProperties.length];
			for (int i = 0; i < platformProperties.length; i++)
				this.platformProperties[i] = new Hashtable(PROPS.length);
		}
		boolean result = false;
		for (int i = 0; i < platformProperties.length; i++)
			result |= setProps(this.platformProperties[i], platformProperties[0]);
		return result;
	}

	public Dictionary[] getPlatformProperties() {
		return platformProperties;
	}

	private boolean checkProp(Object origObj, Object newObj) {
		if ((origObj == null && newObj != null) || (origObj != null && newObj == null))
			return true;
		if (origObj == null)
			return false;
		if (origObj.getClass() != newObj.getClass())
			return true;
		if (origObj instanceof String)
			return !origObj.equals(newObj);
		String[] origProps = (String[]) origObj;
		String[] newProps = (String[]) newObj;
		if (origProps.length != newProps.length)
			return true;
		for (int i = 0; i < origProps.length; i++) {
			if (!origProps[i].equals(newProps[i]))
				return true;
		}
		return false;
	}

	private boolean setProps(Dictionary origProps, Dictionary newProps) {
		boolean changed = false;
		for (int i = 0; i < PROPS.length; i++) {
			Object origProp = origProps.get(PROPS[i]);
			Object newProp = newProps.get(PROPS[i]);
			if (checkProp(origProp, newProp)) {
				changed = true;
				if (newProp == null)
					origProps.remove(PROPS[i]);
				else
					origProps.put(PROPS[i], newProp);
				if (PROPS[i].equals(Constants.OSGI_FRAMEWORK_SYSTEM_PACKAGES))
					setSystemExports((String) newProp);
			}
		}
		return changed;
	}

	public BundleDescription[] getRemovalPendings() {
		return (BundleDescription[]) removalPendings.toArray(new BundleDescription[removalPendings.size()]);
	}

	public synchronized ExportPackageDescription linkDynamicImport(BundleDescription importingBundle, String requestedPackage) {
		if (resolver == null)
			throw new IllegalStateException("no resolver set"); //$NON-NLS-1$
		BundleDescriptionImpl importer = (BundleDescriptionImpl) importingBundle;
		if (importer.getDynamicStamp(requestedPackage) == getTimeStamp())
			return null;
		fullyLoad();
		// ask the resolver to resolve our dynamic import
		ExportPackageDescriptionImpl result = (ExportPackageDescriptionImpl) resolver.resolveDynamicImport(importingBundle, requestedPackage);
		if (result == null)
			importer.setDynamicStamp(requestedPackage, new Long(getTimeStamp()));
		else {
			importer.setDynamicStamp(requestedPackage, null); // remove any cached timestamp
			// need to add the result to the list of resolved imports
			importer.addDynamicResolvedImport(result);
		}
		setDynamicCacheChanged(true);
		return result;
	}

	void setReader(StateReader reader) {
		this.reader = reader;
	}

	StateReader getReader() {
		return reader;
	}

	public void fullyLoad() {
		if (fullyLoaded == true)
			return;
		if (reader != null && reader.isLazyLoaded())
			reader.fullyLoad();
		fullyLoaded = true;
	}

	public void unloadLazyData(long expireTime) {
		// make sure no other thread is trying to unload or load
		synchronized (reader) {
			if (reader.getAccessedFlag()) {
				reader.setAccessedFlag(false); // reset accessed flag
				return;
			}
			BundleDescription[] bundles = getBundles();
			for (int i = 0; i < bundles.length; i++)
				((BundleDescriptionImpl) bundles[i]).unload();
		}
	}

	void setSystemExports(String exportSpec) {
		try {
			ManifestElement[] elements = ManifestElement.parseHeader(Constants.EXPORT_PACKAGE, exportSpec);
			// we can pass false for strict mode here because we never want to mark the system
			// exports as internal.
			systemExports = StateBuilder.createExportPackages(elements, null, null, null, 2, false);
		} catch (BundleException e) {
			// TODO consider throwing this... 
		}
	}

	public ExportPackageDescription[] getSystemPackages() {
		if (systemExports == null)
			return new ExportPackageDescription[0];
		return systemExports;
	}

	boolean inStrictMode() {
		return Constants.STRICT_MODE.equals(getPlatformProperties()[0].get(Constants.OSGI_RESOLVER_MODE));
	}

	public boolean dynamicCacheChanged() {
		return dynamicCacheChanged;
	}
		 
	void setDynamicCacheChanged(boolean dynamicCacheChanged) {
		this.dynamicCacheChanged = dynamicCacheChanged;
	}
}
