/*******************************************************************************
 * Copyright (c) 2008 Code 9 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: 
 *   Code 9 - initial API and implementation
 ******************************************************************************/
package org.eclipse.equinox.internal.p2.publisher.actions;

import java.io.*;
import java.util.*;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.equinox.internal.p2.core.helpers.FileUtils;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
import org.eclipse.equinox.internal.p2.publisher.*;
import org.eclipse.equinox.internal.p2.publisher.features.*;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.ArtifactDescriptor;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactDescriptor;
import org.eclipse.equinox.internal.provisional.p2.metadata.*;
import org.eclipse.equinox.internal.provisional.p2.metadata.MetadataFactory.InstallableUnitDescription;
import org.eclipse.osgi.service.resolver.VersionRange;
import org.osgi.framework.Version;

/**
 * Publish IUs for all of the features in the given set of locations.  The locations can 
 * be actual locations of the features or folders of features.
 */
public class FeaturesAction extends AbstractPublishingAction {
	public static final String INSTALL_FEATURES_FILTER = "(org.eclipse.update.install.features=true)"; //$NON-NLS-1$

	protected Feature[] featureList;

	public static String getTransformedId(String original, boolean isPlugin, boolean isGroup) {
		return (isPlugin ? original : original + (isGroup ? ".feature.group" : ".feature.jar")); //$NON-NLS-1$//$NON-NLS-2$
	}

	public static IArtifactKey createFeatureArtifactKey(String id, String version) {
		return new ArtifactKey(MetadataGeneratorHelper.ECLIPSE_FEATURE_CLASSIFIER, id, new Version(version));
	}

	public FeaturesAction(File[] locations) {
		featureList = getFeatures(expandLocations(locations));
	}

	public FeaturesAction(Feature[] featureList) {
		this.featureList = featureList;
	}

	public IStatus perform(IPublisherInfo info, IPublisherResult results) {
		generateFeatureIUs(featureList, results, info);
		return Status.OK_STATUS;
	}

	private File[] expandLocations(File[] list) {
		ArrayList result = new ArrayList();
		expandLocations(list, result);
		return (File[]) result.toArray(new File[result.size()]);
	}

	private void expandLocations(File[] list, ArrayList result) {
		if (list == null)
			return;
		for (int i = 0; i < list.length; i++) {
			File location = list[i];
			if (location.isDirectory()) {
				// if the location is itself a feature, just add it.  Otherwise r down
				if (!new File(location, "feature.xml").exists())
					expandLocations(location.listFiles(), result);
				else
					result.add(location);
			} else {
				result.add(location);
			}
		}
	}

	protected void generateFeatureIUs(Feature[] features, IPublisherResult result, IPublisherInfo info) {
		// Build Feature IUs, and add them to any corresponding categories
		for (int i = 0; i < features.length; i++) {
			Feature feature = features[i];
			// The IU hierarchy must be built from the bottom up so do the root files first.
			ArrayList childIUs = generateRootFileIUs(feature, result, info);
			IInstallableUnit featureIU = createFeatureJarIU(feature, childIUs, info);
			publishFeatureArtifacts(feature, featureIU, info);
			gatherBundleShapeAdvice(feature, info);
			// create the associated group and register the feature and group in the result.
			IInstallableUnit groupIU = createGroupIU(feature, featureIU, null);
			result.addIU(groupIU, IPublisherResult.ROOT);
			result.addIU(featureIU, IPublisherResult.ROOT);
		}
	}

	protected IInstallableUnit createFeatureJarIU(Feature feature, ArrayList childIUs, IPublisherInfo info) {
		// create the basic feature IU with all the children
		String location = feature.getLocation();
		boolean isExploded = (location.endsWith(".jar") ? false : true); //$NON-NLS-1$
		Properties props = getFeatureAdvice(feature, info);
		IInstallableUnit featureIU = createFeatureJarIU(feature, childIUs, isExploded, props);
		return featureIU;
	}

	protected void publishFeatureArtifacts(Feature feature, IInstallableUnit featureIU, IPublisherInfo info) {
		// add all the artifacts associated with the feature
		// TODO this is a little strange.  If there are several artifacts, how do we know which files go with
		// which artifacts when we publish them?  For now it would be surprising to have more than one
		// artifact per feature IU.
		IArtifactKey[] artifacts = featureIU.getArtifacts();
		for (int j = 0; j < artifacts.length; j++) {
			File file = new File(feature.getLocation());
			IArtifactDescriptor ad = MetadataGeneratorHelper.createArtifactDescriptor(artifacts[j], file);
			// if the artifact is a dir and we are not doing "AS_IS", zip it up.
			if (file.isDirectory() && !((info.getArtifactOptions() & IPublisherInfo.A_AS_IS) > 0))
				publishArtifact(ad, file.listFiles(), info, INCLUDE_ROOT);
			else
				publishArtifact(ad, new File[] {file}, info, AS_IS | INCLUDE_ROOT);
		}
	}

	private Properties getFeatureAdvice(Feature feature, IPublisherInfo info) {
		Properties result = new Properties();
		Collection advice = info.getAdvice(null, false, null, null, IFeatureAdvice.class);
		for (Iterator i = advice.iterator(); i.hasNext();) {
			IFeatureAdvice entry = (IFeatureAdvice) i.next();
			Properties props = entry.getProperties(feature, null);
			if (props != null)
				result.putAll(props);
		}
		return result;
	}

	protected ArrayList generateRootFileIUs(Feature feature, IPublisherResult result, IPublisherInfo info) {
		File location = new File(feature.getLocation());
		Properties props = loadProperties(location, "build.properties");
		return generateRootFileIUs(feature.getId(), feature.getVersion(), props, location, result, info);
	}

	private ArrayList generateRootFileIUs(String featureId, String featureVersion, Properties props, File location, IPublisherResult result, IPublisherInfo info) {
		ArrayList ius = new ArrayList();
		FileSetDescriptor[] rootFileDescriptors = getRootFileDescriptors(props);
		for (int i = 0; i < rootFileDescriptors.length; i++) {
			IInstallableUnit iu = generateRootFileIU(featureId, featureVersion, location, rootFileDescriptors[i], result, info);
			ius.add(iu);
		}
		return ius;
	}

	private Properties loadProperties(File location, String file) {
		Properties props = new Properties();
		File tempFile = null;
		try {
			// if the feature is a dir then just return the location
			if (!location.isDirectory()) {
				// otherwise extract the JAR into a temp location and return that location
				tempFile = File.createTempFile("p2.generator", ""); //$NON-NLS-1$ //$NON-NLS-2$
				FileUtils.unzipFile(location, tempFile);
				location = tempFile;
			}
			try {
				InputStream in = null;
				try {
					in = new BufferedInputStream(new FileInputStream(new File(location, file))); //$NON-NLS-1$
					props.load(in);
				} finally {
					if (in != null)
						in.close();
				}
			} catch (FileNotFoundException e) {
				// ignore if it is just a file not found.
			} catch (IOException e) {
				LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Error parsing " + file, e)); //$NON-NLS-1$
			}
		} catch (IOException e) {
			LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Error publishing artifacts", e)); //$NON-NLS-1$
		} finally {
			if (tempFile != null)
				tempFile.delete();
		}
		return props;
	}

	private IInstallableUnit generateRootFileIU(String featureId, String featureVersion, File location, FileSetDescriptor rootFile, IPublisherResult result, IPublisherInfo info) {
		Object[] iuAndFiles = MetadataGeneratorHelper.createFeatureRootFileIU(featureId, featureVersion, location, rootFile);
		IInstallableUnit iuResult = (IInstallableUnit) iuAndFiles[0];
		File[] fileResult = (File[]) iuAndFiles[1];
		if (fileResult != null && fileResult.length > 0) {
			IArtifactKey artifact = iuResult.getArtifacts()[0];
			ArtifactDescriptor descriptor = new ArtifactDescriptor(artifact);
			publishArtifact(descriptor, fileResult, info, 0);
		}
		result.addIU(iuResult, IPublisherResult.NON_ROOT);
		return iuResult;
	}

	protected FileSetDescriptor[] getRootFileDescriptors(Properties props) {
		HashMap result = new HashMap();
		for (Iterator i = props.keySet().iterator(); i.hasNext();) {
			String property = (String) i.next();
			// we only care about root properties
			if (!property.startsWith("root.")) //$NON-NLS-1$
				continue;
			String[] spec = getArrayFromString(property, "."); //$NON-NLS-1$
			String descriptorKey = spec[0];
			String configSpec = null;
			// if the spec is 4 or more then there must be a config involved to get it
			if (spec.length > 3) {
				configSpec = createConfigSpec(spec[2], spec[1], spec[3]);
				descriptorKey += "." + createIdString(configSpec); //$NON-NLS-1$
			}

			FileSetDescriptor descriptor = (FileSetDescriptor) result.get(descriptorKey);
			if (descriptor == null) {
				descriptor = new FileSetDescriptor(descriptorKey, configSpec);
				result.put(descriptorKey, descriptor);
			}
			// if the last segment in the spec is "link" 
			if (spec[spec.length - 1] == "link") //$NON-NLS-1$
				descriptor.setLinks(props.getProperty(property));
			else {
				// if the second last segment is "permissions" 
				if (spec[spec.length - 2].equals("permissions")) //$NON-NLS-1$
					descriptor.addPermissions(new String[] {spec[spec.length - 1], props.getProperty(property)});
				else {
					// so it is not a link or a permissions, it must be a straight file copy (with or without a config)
					descriptor.setFiles(props.getProperty(property));
				}
			}
		}
		Collection values = result.values();
		return (FileSetDescriptor[]) values.toArray(new FileSetDescriptor[values.size()]);
	}

	/**
	 * Gather any advice we can from the given feature.  In particular, it may have
	 * information about the shape of the bundles it includes.  The discovered advice is
	 * added to the given result.
	 * @param feature the feature to process
	 * @param info the publishing info to update
	 */
	public void gatherBundleShapeAdvice(Feature feature, IPublisherInfo info) {
		FeatureEntry entries[] = feature.getEntries();
		for (int i = 0; i < entries.length; i++) {
			FeatureEntry entry = entries[i];
			if (entry.isUnpack())
				info.addAdvice(new BundleShapeAdvice(entry.getId(), new Version(entry.getVersion()), IBundleShapeAdvice.DIR));
		}
	}

	public IInstallableUnit createFeatureJarIU(Feature feature, ArrayList childIUs, boolean isExploded, Properties extraProperties) {
		InstallableUnitDescription iu = new MetadataFactory.InstallableUnitDescription();
		String id = getTransformedId(feature.getId(), /*isPlugin*/false, /*isGroup*/false);
		iu.setId(id);
		Version version = new Version(feature.getVersion());
		iu.setVersion(version);
		if (feature.getLicense() != null)
			iu.setLicense(new License(feature.getLicenseURL(), feature.getLicense()));
		if (feature.getCopyright() != null)
			iu.setCopyright(new Copyright(feature.getCopyrightURL(), feature.getCopyright()));

		// The required capabilities are not specified at this level because we don't want the feature jar to be attractive to install.

		iu.setTouchpointType(MetadataGeneratorHelper.TOUCHPOINT_OSGI);
		iu.setFilter(INSTALL_FEATURES_FILTER);
		iu.setSingleton(true);

		if (feature.getInstallHandler() != null && feature.getInstallHandler().trim().length() > 0) {
			String installHandlerProperty = "handler=" + feature.getInstallHandler(); //$NON-NLS-1$

			if (feature.getInstallHandlerLibrary() != null)
				installHandlerProperty += ", library=" + feature.getInstallHandlerLibrary(); //$NON-NLS-1$

			if (feature.getInstallHandlerURL() != null)
				installHandlerProperty += ", url=" + feature.getInstallHandlerURL(); //$NON-NLS-1$

			iu.setProperty(MetadataGeneratorHelper.ECLIPSE_INSTALL_HANDLER_PROP, installHandlerProperty);
		}

		iu.setCapabilities(new ProvidedCapability[] {MetadataGeneratorHelper.createSelfCapability(id, version), MetadataGeneratorHelper.FEATURE_CAPABILITY, MetadataFactory.createProvidedCapability(MetadataGeneratorHelper.CAPABILITY_NS_UPDATE_FEATURE, feature.getId(), version)});
		iu.setArtifacts(new IArtifactKey[] {createFeatureArtifactKey(feature.getId(), version.toString())});

		// link in all the children (if any) as requirements.
		// TODO consider if these should be linked as exact version numbers.  Should be ok but may be brittle.
		if (childIUs != null) {
			RequiredCapability[] required = new RequiredCapability[childIUs.size()];
			for (int i = 0; i < childIUs.size(); i++) {
				IInstallableUnit child = (IInstallableUnit) childIUs.get(i);
				required[i] = MetadataFactory.createRequiredCapability(MetadataGeneratorHelper.IU_NAMESPACE, child.getId(), new VersionRange(child.getVersion(), true, child.getVersion(), true), INSTALL_FEATURES_FILTER, false, false);
			}
			iu.setRequiredCapabilities(required);
		}

		if (isExploded) {
			// Define the immutable metadata for this IU. In this case immutable means
			// that this is something that will not impact the configuration.
			Map touchpointData = new HashMap();
			touchpointData.put("zipped", "true"); //$NON-NLS-1$ //$NON-NLS-2$
			iu.addTouchpointData(MetadataFactory.createTouchpointData(touchpointData));
		}

		if (extraProperties != null) {
			Enumeration e = extraProperties.propertyNames();
			while (e.hasMoreElements()) {
				String name = (String) e.nextElement();
				iu.setProperty(name, extraProperties.getProperty(name));
			}
		}

		return MetadataFactory.createInstallableUnit(iu);
	}

	public IInstallableUnit createGroupIU(Feature feature, IInstallableUnit featureIU, Properties extraProperties) {
		InstallableUnitDescription iu = new MetadataFactory.InstallableUnitDescription();
		String id = getTransformedId(feature.getId(), /*isPlugin*/false, /*isGroup*/true);
		iu.setId(id);
		Version version = new Version(feature.getVersion());
		iu.setVersion(version);
		iu.setProperty(IInstallableUnit.PROP_NAME, feature.getLabel());
		if (feature.getLicense() != null)
			iu.setLicense(new License(feature.getLicenseURL(), feature.getLicense()));
		if (feature.getCopyright() != null)
			iu.setCopyright(new Copyright(feature.getCopyrightURL(), feature.getCopyright()));
		iu.setUpdateDescriptor(MetadataFactory.createUpdateDescriptor(id, new VersionRange(new Version(0, 0, 0), true, new Version(feature.getVersion()), false), IUpdateDescriptor.NORMAL, null));

		// generate requirements for the feature inclusions/requirement 
		FeatureEntry entries[] = feature.getEntries();
		RequiredCapability[] required = new RequiredCapability[entries.length + 1];
		for (int i = 0; i < entries.length; i++) {
			VersionRange range = getVersionRange(entries[i]);
			required[i] = MetadataFactory.createRequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, getTransformedId(entries[i].getId(), entries[i].isPlugin(), /*isGroup*/true), range, getFilter(entries[i]), entries[i].isOptional(), false);
		}
		required[entries.length] = MetadataFactory.createRequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, featureIU.getId(), new VersionRange(featureIU.getVersion(), true, featureIU.getVersion(), true), INSTALL_FEATURES_FILTER, false, false);
		iu.setRequiredCapabilities(required);
		iu.setTouchpointType(TouchpointType.NONE);
		iu.setProperty(IInstallableUnit.PROP_TYPE_GROUP, Boolean.TRUE.toString());
		// TODO: shouldn't the filter for the group be constructed from os, ws, arch, nl
		// 		 of the feature?
		// iu.setFilter(filter);
		iu.setCapabilities(new ProvidedCapability[] {MetadataGeneratorHelper.createSelfCapability(id, version)});

		if (extraProperties != null) {
			Enumeration e = extraProperties.propertyNames();
			while (e.hasMoreElements()) {
				String name = (String) e.nextElement();
				iu.setProperty(name, extraProperties.getProperty(name));
			}
		}
		return MetadataFactory.createInstallableUnit(iu);
	}

	public VersionRange getVersionRange(FeatureEntry entry) {
		String versionSpec = entry.getVersion();
		if (versionSpec == null)
			// TODO should really be returning VersionRange.emptyRange here...
			return null;
		Version version = new Version(versionSpec);
		// if this is an includes then return either a completely open range (if the verison is 0.0.0)
		// or an exact range
		if (!entry.isRequires()) {
			if (version.equals(Version.emptyVersion))
				return VersionRange.emptyRange;
			return new VersionRange(version, true, version, true);
		}
		String match = entry.getMatch();
		if (match == null)
			// TODO should really be returning VersionRange.emptyRange here...
			return null;
		if (match.equals("perfect")) //$NON-NLS-1$
			return new VersionRange(version, true, version, true);
		if (match.equals("equivalent")) { //$NON-NLS-1$
			Version upper = new Version(version.getMajor(), version.getMinor() + 1, 0);
			return new VersionRange(version, true, upper, false);
		}
		if (match.equals("compatible")) { //$NON-NLS-1$
			Version upper = new Version(version.getMajor() + 1, 0, 0);
			return new VersionRange(version, true, upper, false);
		}
		if (match.equals("greaterOrEqual")) //$NON-NLS-1$
			return new VersionRange(version, true, new VersionRange(null).getMaximum(), true);
		return null;
	}

	public String getFilter(FeatureEntry entry) {
		StringBuffer result = new StringBuffer();
		result.append("(&"); //$NON-NLS-1$
		if (entry.getFilter() != null)
			result.append(entry.getFilter());
		if (entry.getOS() != null)
			result.append("(osgi.os=" + entry.getOS() + ')');//$NON-NLS-1$
		if (entry.getWS() != null)
			result.append("(osgi.ws=" + entry.getWS() + ')');//$NON-NLS-1$
		if (entry.getArch() != null)
			result.append("(osgi.arch=" + entry.getArch() + ')');//$NON-NLS-1$
		if (entry.getNL() != null)
			result.append("(osgi.nl=" + entry.getNL() + ')');//$NON-NLS-1$
		if (result.length() == 2)
			return null;
		result.append(')');
		return result.toString();
	}

	protected Feature[] getFeatures(File[] locations) {
		ArrayList result = new ArrayList(locations.length);
		for (int i = 0; i < locations.length; i++) {
			Feature feature = new FeatureParser().parse(locations[i]);
			if (feature != null) {
				feature.setLocation(locations[i].getAbsolutePath());
				result.add(feature);
			}
		}
		return (Feature[]) result.toArray(new Feature[result.size()]);
	}
}
