/*******************************************************************************
 *  Copyright (c) 2005, 2022 IBM Corporation and others.
 *
 *  This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License 2.0
 *  which accompanies this distribution, and is available at
 *  https://www.eclipse.org/legal/epl-2.0/
 *
 *  SPDX-License-Identifier: EPL-2.0
 *
 *  Contributors:
 *     IBM Corporation - initial API and implementation
 *     Karsten Thoms <karsten.thoms@itemis.de> - Bug 522332
 *     Hannes Wellmann - Bug 539637 major rework to consider versions and improve runtime behavior
 *******************************************************************************/
package org.eclipse.pde.internal.core;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.service.resolver.State;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.core.plugin.PluginRegistry;
import org.eclipse.pde.core.target.ITargetPlatformService;
import org.eclipse.pde.core.target.NameVersionDescriptor;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;

/**
 * Utility class to return bundle description collections for a variety of
 * dependency scenarios
 *
 * @noextend This class is not intended to be subclassed by clients.
 * @noinstantiate This class is not intended to be instantiated by clients.
 */
public class DependencyManager {

	private DependencyManager() { // static use only
	}

	public enum Options {
		/** Specifies to include all optional dependencies into the closure. */
		INCLUDE_OPTIONAL_DEPENDENCIES,

		/**
		 * Specifies to include all fragments into the closure (must not be
		 * combined with {@link #INCLUDE_NON_TEST_FRAGMENTS}).
		 */
		INCLUDE_ALL_FRAGMENTS,
		/**
		 * Specifies to include all non-test fragments into the closure (must
		 * not be combined with {@link #INCLUDE_ALL_FRAGMENTS}).
		 */
		INCLUDE_NON_TEST_FRAGMENTS;
	}

	/**
	 * Returns a {@link Set} of bundle descriptions of the given
	 * {@link IPluginModelBase}s and all of their required dependencies
	 * (including optional) and fragments.
	 * <p>
	 * The set includes the descriptions of the given model bases as well as all
	 * transitively computed explicit, implicit (defined in the target-platform)
	 * and optional dependencies. So it is the self-contained closure for all
	 * required dependencies of the given set of plug-ins plus the implicit
	 * dependencies defined in the target platform.
	 * </p>
	 *
	 * @param plugins
	 *            the collection of {@link IPluginModelBase}s to compute
	 *            dependencies for
	 * @return a set of bundle descriptions
	 */
	public static Set<BundleDescription> getSelfAndDependencies(Collection<IPluginModelBase> plugins) {
		Collection<NameVersionDescriptor> implicit = getImplicitDependencies();
		List<BundleDescription> bundles = mergeBundleDescriptions(plugins, implicit, TargetPlatformHelper.getState());
		return findRequirementsClosure(bundles, Options.INCLUDE_OPTIONAL_DEPENDENCIES, Options.INCLUDE_ALL_FRAGMENTS);
	}

	/**
	 * Returns a {@link Set} of bundle descriptions for all required
	 * dependencies of the given objects from the given {@link State}.
	 * <p>
	 * The set includes the descriptions of all transitively computed explicit
	 * dependencies. The set does not include the descriptions of the given
	 * objects and only includes optional dependencies if requested.
	 * </p>
	 *
	 * @param plugins
	 *            the group of {@link IPluginModelBase}s to compute dependencies
	 *            for.
	 * @param implicit
	 *            the array of additional implicit dependencies to add to the
	 *            {@link Set}
	 * @param state
	 *            the {@link State} to compute the dependencies in
	 * @param options
	 *            the specified {@link Options} for computing the closure
	 * @return a set of bundle descriptions
	 */
	public static Set<BundleDescription> getDependencies(Collection<IPluginModelBase> plugins,
			Collection<NameVersionDescriptor> implicit, State state, Options... options) {
		List<BundleDescription> bundles = mergeBundleDescriptions(plugins, implicit, state);
		Set<BundleDescription> closure = findRequirementsClosure(bundles, options);
		plugins.forEach(p -> closure.remove(p.getBundleDescription()));
		return closure;
	}

	/**
	 * Returns a {@link Set} of bundle descriptions for all required
	 * dependencies of the given {@link IPluginModelBase}s.
	 * <p>
	 * The set includes the descriptions of the transitively computed explicit,
	 * implicit (defined in the target-platform) and optional (if requested)
	 * dependencies. The set does not include the descriptions of the given
	 * objects.
	 * </p>
	 *
	 * @param plugins
	 *            selected the group of {@link IPluginModelBase}s to compute
	 *            dependencies for.
	 * @param options
	 *            the specified {@link Options} for computing the closure
	 * @return a set of bundle descriptions
	 */
	public static Set<BundleDescription> getDependencies(Collection<IPluginModelBase> plugins, Options... options) {
		return getDependencies(plugins, getImplicitDependencies(), TargetPlatformHelper.getState(), options);
	}

	/**
	 * Returns a {@link Set} of bundle descriptions of the given
	 * {@link IPluginModelBase}s and all of their required dependencies.
	 * <p>
	 * The set includes the descriptions of the given bundle descriptions as
	 * well as all transitively computed explicit and optional (if requested)
	 * dependencies. So it is the self-contained closure for all required
	 * dependencies of the given set of plug-ins.
	 * </p>
	 *
	 * @param bundles
	 *            the group of {@link BundleDescription}s to compute
	 *            dependencies for.
	 * @param options
	 *            the specified {@link Options} for computing the closure
	 * @return a set of bundle descriptions
	 */
	public static Set<BundleDescription> findRequirementsClosure(Collection<BundleDescription> bundles,
			Options... options) {

		Set<Options> optionSet = Set.of(options);
		boolean includeOptional = optionSet.contains(Options.INCLUDE_OPTIONAL_DEPENDENCIES);
		boolean includeAllFragments = optionSet.contains(Options.INCLUDE_ALL_FRAGMENTS);
		boolean includeNonTestFragments = optionSet.contains(Options.INCLUDE_NON_TEST_FRAGMENTS);
		if (includeAllFragments && includeNonTestFragments) {
			throw new AssertionError("Cannot combine INCLUDE_ALL_FRAGMENTS and INCLUDE_NON_TEST_FRAGMENTS"); //$NON-NLS-1$
		}

		Set<BundleDescription> closure = new HashSet<>(bundles.size() * 4 / 3 + 1);
		Queue<BundleDescription> pending = new ArrayDeque<>();

		// initialize with given bundles
		for (BundleDescription bundle : bundles) {
			addNewRequiredBundle(bundle, closure, pending);
		}

		// perform exhaustive iterative bfs for required wires
		while (!pending.isEmpty()) {
			BundleDescription bundle = pending.remove();

			BundleWiring wiring = bundle.getWiring();
			if (wiring == null || !wiring.isInUse()) {
				continue;
			}

			List<BundleWire> requiredWires = wiring.getRequiredWires(null);
			for (BundleWire wire : requiredWires) {
				BundleRevision provider = getProvider(wire);
				if (provider instanceof BundleDescription && (includeOptional || !isOptional(wire.getRequirement()))) {
					BundleDescription requiredBundle = (BundleDescription) provider;
					addNewRequiredBundle(requiredBundle, closure, pending);
				}
			}

			if (includeAllFragments || includeNonTestFragments) {
				// A fragment's host is already required by a wire
				for (BundleDescription fragment : bundle.getFragments()) {
					if (includeAllFragments || !isTestWorkspaceProject(fragment)) {
						addNewRequiredBundle(fragment, closure, pending);
					}
				}
			}
		}
		return closure;
	}

	private static void addNewRequiredBundle(BundleDescription bundle, Set<BundleDescription> requiredBundles,
			Queue<BundleDescription> pending) {
		if (bundle != null && bundle.isResolved() && !bundle.isRemovalPending() && requiredBundles.add(bundle)) {
			pending.add(bundle);
		}
	}

	private static BundleRevision getProvider(BundleWire wire) {
		// org.eclipse.osgi.internal.resolver.BundleDescriptionImpl.BundleWireImpl.getProvider()
		// does not check for null
		BundleWiring providerWiring = wire.getProviderWiring();
		return providerWiring != null ? providerWiring.getRevision() : null;
	}

	private static boolean isOptional(BundleRequirement requirement) {
		return Constants.RESOLUTION_OPTIONAL.equals(requirement.getDirectives().get(Constants.RESOLUTION_DIRECTIVE));
	}

	private static boolean isTestWorkspaceProject(BundleDescription f) {
		// Be defensive when declaring a fragment as 'test'-fragment
		IPluginModelBase pluginModel = PluginRegistry.findModel(f);
		if (pluginModel != null) {
			IResource resource = pluginModel.getUnderlyingResource();
			if (resource != null) {
				return ClasspathComputer.hasTestOnlyClasspath(resource.getProject());
			} // test-fragments are usually not part of the target-platform
		}
		return false;
	}

	/**
	 * Computes the set of implicit dependencies from the
	 * {@link PDEPreferencesManager}.
	 *
	 * @return a set of bundle ids
	 */
	private static Collection<NameVersionDescriptor> getImplicitDependencies() {
		try {
			ITargetPlatformService service = PDECore.getDefault().acquireService(ITargetPlatformService.class);
			if (service != null) {
				NameVersionDescriptor[] implicit = service.getWorkspaceTargetDefinition().getImplicitDependencies();
				if (implicit != null) {
					return Arrays.asList(implicit);
				}
			}
		} catch (CoreException e) {
			PDECore.log(e);
		}
		return Collections.emptyList();
	}

	private static List<BundleDescription> mergeBundleDescriptions(Collection<IPluginModelBase> plugins,
			Collection<NameVersionDescriptor> descriptors, State state) {
		List<BundleDescription> bundles = new ArrayList<>();
		for (IPluginModelBase plugin : plugins) {
			if (plugin != null) {
				bundles.add(plugin.getBundleDescription());
			}
		}
		for (NameVersionDescriptor descriptor : descriptors) {
			String versionStr = descriptor.getVersion();
			Version version = versionStr != null ? Version.parseVersion(versionStr) : null;
			BundleDescription bundle = state.getBundle(descriptor.getId(), version);
			bundles.add(bundle);
		}
		return bundles;
	}
}
