/*******************************************************************************
 * Copyright (c) 2011 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 - Initial API and implementation
 ******************************************************************************/
package org.eclipse.equinox.internal.resolver;

import java.util.*;
import java.util.Map.Entry;
import org.eclipse.equinox.internal.resolver.FilterParser.FilterComponent;
import org.eclipse.osgi.service.resolver.*;
import org.eclipse.osgi.service.resolver.extras.*;
import org.osgi.framework.*;
import org.osgi.framework.hooks.resolver.ResolverHook;
import org.osgi.framework.hooks.resolver.ResolverHookFactory;
import org.osgi.framework.resource.*;
import org.osgi.framework.wiring.*;
import org.osgi.service.resolver.Environment;
import org.osgi.service.resolver.ResolutionException;

public class EquinoxResolverHook implements ResolverHookFactory, ResolverHook {
	private final State state;
	private final Environment environment;
	private final Map<Resource, Map<String, List<Wire>>> wiring;
	private final Map<Resource, BundleDescription> resourceToDescription = new HashMap<Resource, BundleDescription>();

	public EquinoxResolverHook(State state, Environment environment) {
		this.state = state;
		this.environment = environment;
		Map<Resource, List<Wire>> envWiring = environment.getWiring();
		this.wiring = new HashMap<Resource, Map<String, List<Wire>>>();
		if (envWiring != null) {
			for (Map.Entry<Resource, List<Wire>> wires : envWiring.entrySet()) {
				Map<String, List<Wire>> mappedWires = new HashMap<String, List<Wire>>();
				this.wiring.put(wires.getKey(), mappedWires);
				for (Wire wire : wires.getValue()) {
					String namespace = wire.getRequirement().getNamespace();
					List<Wire> namespaceWires = mappedWires.get(namespace);
					if (namespaceWires == null) {
						namespaceWires = new ArrayList<Wire>();
						mappedWires.put(namespace, namespaceWires);
					}
					namespaceWires.add(wire);
				}
			}
		}
	}

	public Map<Resource, List<Wire>> resolve(Collection<? extends Resource> mandatoryResources, Collection<? extends Resource> optionalResources) throws ResolutionException {
		if (mandatoryResources == null)
			mandatoryResources = Collections.emptyList();
		if (optionalResources == null)
			optionalResources = Collections.emptyList();
		if (mandatoryResources.isEmpty() && optionalResources.isEmpty())
			return Collections.emptyMap();

		// Populate the Equinox State with the initial set of resolved resources
		for (Resource resource : wiring.keySet()) {
			state.addBundle(createDescription(resource));
		}
		// resolve the existing resources according to the wiring
		if (!wiring.isEmpty())
			state.resolve();
		// all descriptions added up to this point must be resolved.
		for (BundleDescription description : resourceToDescription.values()) {
			if (!description.isResolved())
				throw new ResolutionException("Could not resolve the resource: " + description.getUserObject()); //$NON-NLS-1$
		}
		// Populate the Equinox State with the initial set of mandatory/optional resources
		for (Resource resource : mandatoryResources)
			state.addBundle(createDescription(resource));
		for (Resource resource : optionalResources)
			state.addBundle(createDescription(resource));

		Map<Resource, List<Wire>> result = new HashMap<Resource, List<Wire>>();
		state.resolve();

		List<BundleDescription> unresolvedMandatory = new ArrayList<BundleDescription>(mandatoryResources.size());
		for (Resource resource : mandatoryResources) {
			BundleDescription description = resourceToDescription.get(resource);
			if (!description.isResolved())
				unresolvedMandatory.add(description);
			else
				addWires(result, description);
		}
		if (!unresolvedMandatory.isEmpty()) {
			// TODO need to make a better error message here
			throw new ResolutionException("Could not resolve mandatory resources: " + unresolvedMandatory); //$NON-NLS-1$
		}

		for (Resource resource : optionalResources) {
			BundleDescription description = resourceToDescription.get(resource);
			if (description.isResolved())
				addWires(result, description);
		}

		return result;
	}

	private void addWires(Map<Resource, List<Wire>> result, BundleDescription resolved) {
		Resource resource = (Resource) resolved.getUserObject();
		if (result.get(resource) != null || wiring.get(resource) != null)
			return; // already processed or previously resolved
		BundleWiring bundleWiring = resolved.getWiring();
		List<BundleWire> bundleWires = bundleWiring.getRequiredWires(null);
		List<Wire> wires = new ArrayList<Wire>(bundleWires.size());
		result.put(resource, wires);
		for (BundleWire bundleWire : bundleWires) {
			final Resource requirer = (Resource) ((BundleDescription) bundleWire.getRequirer()).getUserObject();
			final Resource provider = (Resource) ((BundleDescription) bundleWire.getProvider()).getUserObject();

			final Requirement requirement = (Requirement) ((SpecificationReference) bundleWire.getRequirement()).getSpecification().getUserObject();
			final Capability capability;
			BundleDescription capabilityDescription;
			if (BundleRevision.HOST_NAMESPACE.equals(requirement.getNamespace()) || BundleRevision.BUNDLE_NAMESPACE.equals(requirement.getNamespace())) {
				List<Capability> capabilities = provider.getCapabilities(requirement.getNamespace());
				capability = capabilities.get(0);
				capabilityDescription = (BundleDescription) bundleWire.getProvider();
			} else {
				BaseDescription baseDescription = ((DescriptionReference) bundleWire.getCapability()).getDescription();
				capabilityDescription = baseDescription.getSupplier();
				capability = (Capability) baseDescription.getUserObject();
			}

			addWires(result, capabilityDescription);

			wires.add(new Wire() {
				public Resource getRequirer() {
					return requirer;
				}

				public Requirement getRequirement() {
					return requirement;
				}

				public Resource getProvider() {
					return provider;
				}

				public Capability getCapability() {
					return capability;
				}

				public String toString() {
					return "[" + requirer + ':' + requirement.getResource() + ':' + requirement + "] -> [" + provider + ':' + capability.getResource() + ':' + capability + ']'; //$NON-NLS-1$ //$NON-NLS-2$
				}
			});
		}
	}

	Capability getOriginalCapability(Capability capability) {
		if (BundleRevision.HOST_NAMESPACE.equals(capability.getNamespace()) || BundleRevision.BUNDLE_NAMESPACE.equals(capability.getNamespace())) {
			Resource provider = (Resource) ((BundleDescription) capability.getResource()).getUserObject();
			List<Capability> capabilities = provider.getCapabilities(capability.getNamespace());
			return capabilities.get(0);
		}
		return (Capability) ((DescriptionReference) capability).getDescription().getUserObject();
	}

	private BundleDescription createDescription(Resource resource) {
		BundleDescription description = resourceToDescription.get(resource);
		if (description != null)
			return description;
		Collection<Capability> idList = resource.getCapabilities(ResourceConstants.IDENTITY_NAMESPACE);
		if (idList.size() != 1)
			throw new IllegalArgumentException("Bogus osgi.identity: " + idList); //$NON-NLS-1$
		Capability id = idList.iterator().next();

		Map<String, Object> idAttrs = new HashMap<String, Object>(id.getAttributes());

		String symbolicName = (String) idAttrs.remove(ResourceConstants.IDENTITY_NAMESPACE);
		Version version = (Version) idAttrs.remove(ResourceConstants.IDENTITY_VERSION_ATTRIBUTE);

		String symbolicNameSpecification = symbolicName + toString(idAttrs, "=", true) + toString(id.getDirectives(), ":=", true); //$NON-NLS-1$ //$NON-NLS-2$

		List<ExportPackageDescription> exportPackages = new ArrayList<ExportPackageDescription>();
		List<GenericDescription> provideCapabilities = new ArrayList<GenericDescription>();
		List<ImportPackageSpecification> importPackages = new ArrayList<ImportPackageSpecification>();
		List<GenericSpecification> requireCapabilities = new ArrayList<GenericSpecification>();
		List<HostSpecification> fragmentHost = new ArrayList<HostSpecification>(0);
		List<BundleSpecification> requireBundles = new ArrayList<BundleSpecification>();

		Collection<Capability> capabilities = resource.getCapabilities(null);

		Capability osgiIdentity = null;
		for (Capability capability : capabilities) {
			String namespace = capability.getNamespace();
			if (ResourceConstants.IDENTITY_NAMESPACE.equals(namespace)) {
				osgiIdentity = capability;
				continue;
			} else if (namespace == null || BundleRevision.HOST_NAMESPACE.equals(namespace) || BundleRevision.BUNDLE_NAMESPACE.equals(namespace)) {
				continue;
			} else if (BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) {
				exportPackages.addAll(creatExportPackage(capability));
			} else {
				provideCapabilities.addAll(createProvideCapability(capability));
			}
		}

		Collection<Requirement> requirements = resource.getRequirements(null);
		for (Requirement requirement : requirements) {
			String namespace = requirement.getNamespace();
			if (namespace == null || !environment.isEffective(requirement)) {
				continue;
			} else if (BundleRevision.BUNDLE_NAMESPACE.equals(namespace)) {
				requireBundles.addAll(createRequireBundle(requirement));
			} else if (BundleRevision.HOST_NAMESPACE.equals(namespace)) {
				fragmentHost.addAll(createFragmentHost(requirement));
			} else if (BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) {
				importPackages.addAll(createImportPackage(requirement));
			} else {
				requireCapabilities.addAll(createRequireCapability(requirement));
			}
		}

		BundleDescription result = state.getFactory().createBundleDescription(state.getHighestBundleId() + 1, symbolicNameSpecification, version, null, requireBundles.toArray(new BundleSpecification[requireBundles.size()]), fragmentHost.size() == 0 ? null : fragmentHost.get(0), importPackages.toArray(new ImportPackageSpecification[importPackages.size()]), exportPackages.toArray(new ExportPackageDescription[exportPackages.size()]), null, null, requireCapabilities.toArray(new GenericSpecification[requireCapabilities.size()]), provideCapabilities.toArray(new GenericDescription[provideCapabilities.size()]), null);
		resourceToDescription.put(resource, result);
		result.setUserObject(resource);
		GenericDescription[] genericDescs = result.getGenericCapabilities();
		for (GenericDescription genericDesc : genericDescs) {
			if (ResourceConstants.IDENTITY_NAMESPACE.equals(genericDesc.getType()))
				genericDesc.setUserObject(osgiIdentity);
		}
		return result;

	}

	private List<ExportPackageDescription> creatExportPackage(Capability capability) {
		Map<String, Object> attributes = new HashMap<String, Object>(capability.getAttributes());
		Map<String, String> directives = capability.getDirectives();
		String packageName = (String) attributes.remove(BundleRevision.PACKAGE_NAMESPACE);
		// remove invalid attributes
		attributes.remove(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE);
		attributes.remove(Constants.BUNDLE_VERSION_ATTRIBUTE);
		String declaration = packageName + toString(attributes, "=", true) + toString(directives, ":=", true); //$NON-NLS-1$//$NON-NLS-2$
		List<ExportPackageDescription> result = state.getFactory().createExportPackageDescriptions(declaration);
		for (ExportPackageDescription export : result) {
			export.setUserObject(capability);
		}
		return result;
	}

	private List<GenericDescription> createProvideCapability(Capability capability) {
		Map<String, Object> attributes = capability.getAttributes();
		Map<String, String> directives = capability.getDirectives();
		if ("osgi.ee".equals(capability.getNamespace())) { //$NON-NLS-1$
			attributes = new HashMap<String, Object>(attributes);
			attributes.remove("x-equinox-ee"); //$NON-NLS-1$
		}
		if (directives.get(Constants.EFFECTIVE_DIRECTIVE) != null) {
			// always remove the effective directive
			directives = new HashMap<String, String>(directives);
			directives.remove(Constants.EFFECTIVE_DIRECTIVE);
		}
		String declaration = capability.getNamespace() + toString(attributes, "=", false) + toString(directives, ":=", true); //$NON-NLS-1$//$NON-NLS-2$
		List<GenericDescription> result = state.getFactory().createGenericDescriptions(declaration);
		for (GenericDescription genericDescription : result) {
			genericDescription.setUserObject(capability);
		}
		return result;
	}

	private List<BundleSpecification> createRequireBundle(Requirement requirement) {
		String declaration = createOSGiRequirement(requirement, BundleRevision.BUNDLE_NAMESPACE, Constants.BUNDLE_VERSION_ATTRIBUTE);
		List<BundleSpecification> result = state.getFactory().createBundleSpecifications(declaration);
		for (BundleSpecification bundleSpecification : result) {
			bundleSpecification.setUserObject(requirement);
		}
		return result;
	}

	private List<HostSpecification> createFragmentHost(Requirement requirement) {
		String declaration = createOSGiRequirement(requirement, BundleRevision.HOST_NAMESPACE, Constants.BUNDLE_VERSION_ATTRIBUTE);
		List<HostSpecification> result = state.getFactory().createHostSpecifications(declaration);
		for (HostSpecification hostSpecification : result) {
			hostSpecification.setUserObject(requirement);
		}
		return result;
	}

	private List<ImportPackageSpecification> createImportPackage(Requirement requirement) {
		String declaration = createOSGiRequirement(requirement, BundleRevision.PACKAGE_NAMESPACE, Constants.VERSION_ATTRIBUTE, Constants.BUNDLE_VERSION_ATTRIBUTE);
		List<ImportPackageSpecification> result = state.getFactory().createImportPackageSpecifications(declaration);
		for (ImportPackageSpecification importPackageSpecification : result) {
			importPackageSpecification.setUserObject(requirement);
		}
		return result;
	}

	private List<GenericSpecification> createRequireCapability(Requirement requirement) {
		Map<String, String> directives = requirement.getDirectives();
		if (directives.get(Constants.EFFECTIVE_DIRECTIVE) != null) {
			// always remove the effective directive; all requirements are effective at this point
			directives = new HashMap<String, String>(directives);
			directives.remove(Constants.EFFECTIVE_DIRECTIVE);
		}
		String declaration = requirement.getNamespace() + toString(requirement.getAttributes(), "=", false) + toString(requirement.getDirectives(), ":=", true); //$NON-NLS-1$ //$NON-NLS-2$
		List<GenericSpecification> result = state.getFactory().createGenericSpecifications(declaration);
		for (GenericSpecification genericSpecification : result) {
			genericSpecification.setUserObject(requirement);
		}
		return result;
	}

	private String createOSGiRequirement(Requirement requirement, String namespace, String... versions) {
		Map<String, String> directives = new HashMap<String, String>(requirement.getDirectives());
		String filter = directives.remove(ResourceConstants.REQUIREMENT_FILTER_DIRECTIVE);
		if (filter == null)
			throw new IllegalArgumentException("No filter directive found:" + requirement); //$NON-NLS-1$
		FilterParser parser = new FilterParser(filter);
		FilterComponent component = null;
		try {
			component = parser.parse();
		} catch (InvalidSyntaxException e) {
			throw new IllegalArgumentException("Invalid filter directive", e); //$NON-NLS-1$
		}
		Map<String, String> matchingAttributes = component.getStandardOSGiAttributes(versions);
		String name = matchingAttributes.remove(namespace);
		if (name == null)
			throw new IllegalArgumentException("Invalid requirement: " + requirement); //$NON-NLS-1$
		return name + toString(matchingAttributes, "=", true) + toString(directives, ":=", true); //$NON-NLS-1$ //$NON-NLS-2$
	}

	public ResolverHook begin(Collection<BundleRevision> triggers) {
		return this;
	}

	public void filterResolvable(Collection<BundleRevision> candidates) {
		// nothing
	}

	public void filterSingletonCollisions(BundleCapability singleton, Collection<BundleCapability> collisionCandidates) {
		// clear all collisions; environment is expected to handle singletons
		collisionCandidates.clear();
		return;
	}

	public void filterMatches(BundleRequirement requirement, Collection<BundleCapability> candidates) {
		// this is quick and dirty way to do this; we know the resources are BundleDescriptions
		BundleDescription description = (BundleDescription) requirement.getResource();
		Resource originalResource = (Resource) description.getUserObject();
		Map<String, List<Wire>> resolvedWires = wiring.get(originalResource);
		if (resolvedWires != null) {
			filterAccordingToWiring(requirement, originalResource, description, resolvedWires, candidates);
		} else {
			filterAccordingToEnvironment(requirement, candidates);
		}
	}

	private void filterAccordingToEnvironment(BundleRequirement requirement, Collection<BundleCapability> candidates) {
		Requirement originalRequirement = (Requirement) ((SpecificationReference) requirement).getSpecification().getUserObject();
		Collection<Capability> envCapabilities = environment.findProviders(originalRequirement);
		// first find new resources that should be added to the state
		boolean added = false;
		for (Capability capability : envCapabilities) {
			Resource originalResource = capability.getResource();
			BundleDescription existing = resourceToDescription.get(originalResource);
			if (existing == null) {
				BundleDescription toAdd = createDescription(originalResource);
				state.addBundle(toAdd);
				added = true;
			}
		}
		if (added)
			return; // do nothing resolver needs to recall us
		// Now filter out the candidates from the resolver according to the environment
		for (Iterator<BundleCapability> iCandidates = candidates.iterator(); iCandidates.hasNext();) {
			BaseDescription description = ((DescriptionReference) iCandidates.next()).getDescription();
			Capability originalCapability;
			if (BundleRevision.HOST_NAMESPACE.equals(requirement.getNamespace()) || BundleRevision.BUNDLE_NAMESPACE.equals(requirement.getNamespace())) {
				Resource provider = (Resource) description.getUserObject();
				List<Capability> hostCapabilities = provider.getCapabilities(requirement.getNamespace());
				originalCapability = hostCapabilities.get(0);
			} else {
				originalCapability = (Capability) description.getUserObject();
			}
			if (!envCapabilities.contains(originalCapability))
				iCandidates.remove();
		}
		if (candidates.size() > 1) {
			if (candidates instanceof Sortable<?>) {
				final List<Capability> sorted = new ArrayList<Capability>(envCapabilities);
				((Sortable<BundleCapability>) candidates).sort(new Comparator<BundleCapability>() {
					public int compare(BundleCapability o1, BundleCapability o2) {
						Capability orig1 = getOriginalCapability(o1);
						Capability orig2 = getOriginalCapability(o2);
						int o1Index = sorted.indexOf(orig1);
						int o2Index = sorted.indexOf(orig2);
						return o1Index - o2Index;
					}
				});
			}
		}
	}

	private Resource getHostResource(Resource originalResource, Map<String, List<Wire>> resolvedWires) {
		if (resolvedWires == null)
			return null;
		List<Wire> hostWires = resolvedWires.get(BundleRevision.HOST_NAMESPACE);
		if (hostWires == null)
			return null;
		return hostWires.size() > 0 ? hostWires.get(0).getCapability().getResource() : null;
	}

	@SuppressWarnings("unchecked")
	private void filterAccordingToWiring(Requirement requirement, Resource originalResource, BundleDescription description, Map<String, List<Wire>> resolvedWires, Collection<BundleCapability> candidates) {
		if (description.getHost() != null && !BundleRevision.HOST_NAMESPACE.equals(requirement.getNamespace())) {
			originalResource = getHostResource(originalResource, resolvedWires);
			resolvedWires = originalResource == null ? Collections.EMPTY_MAP : wiring.get(originalResource);
		}
		List<Wire> namespaceWires = resolvedWires.get(requirement.getNamespace());
		if (namespaceWires == null) {
			candidates.clear();
		} else {
			for (Iterator<BundleCapability> iCandidates = candidates.iterator(); iCandidates.hasNext();) {
				Capability candidate = iCandidates.next();
				Resource origProvider = (Resource) ((BaseDescription) candidate.getResource()).getUserObject();
				Collection<Capability> origCapabilities = origProvider.getCapabilities(candidate.getNamespace());
				boolean found = false;
				wireLoop: for (Wire wire : namespaceWires) {
					for (Capability capability : origCapabilities) {
						if (wire.getCapability().equals(capability)) {
							found = true;
							break wireLoop;
						}
					}
				}
				if (!found)
					iCandidates.remove();
			}
		}
	}

	public void end() {
		// nothing
	}

	static <V> String toString(Map<String, V> map, String assignment, boolean stringsOnly) {
		if (map.isEmpty())
			return ""; //$NON-NLS-1$
		Set<Entry<String, V>> set = map.entrySet();
		StringBuffer sb = new StringBuffer();
		for (Entry<String, V> entry : set) {
			sb.append("; "); //$NON-NLS-1$
			String key = entry.getKey();
			Object value = entry.getValue();
			if (value instanceof List) {
				@SuppressWarnings("unchecked")
				List<Object> list = (List<Object>) value;
				if (list.size() == 0)
					continue;
				Object component = list.get(0);
				String className = component.getClass().getName();
				String type = className.substring(className.lastIndexOf('.') + 1);
				sb.append(key).append(':').append("List<").append(type).append(">").append(assignment).append('"'); //$NON-NLS-1$ //$NON-NLS-2$
				for (Object object : list)
					sb.append(object).append(',');
				sb.setLength(sb.length() - 1);
				sb.append('"');
			} else {
				String type = ""; //$NON-NLS-1$
				if (!(value instanceof String) && !stringsOnly) {
					String className = value.getClass().getName();
					type = ":" + className.substring(className.lastIndexOf('.') + 1); //$NON-NLS-1$
				}
				sb.append(key).append(type).append(assignment).append('"').append(value).append('"');
			}
		}
		return sb.toString();
	}
}
