/*******************************************************************************
 * Copyright (c) 2000, 2008 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
 *     James D Miles (IBM Corp.) - bug 191368, Policy URL doesn't support UTF-8 characters
 *******************************************************************************/
package org.eclipse.update.internal.operations;

import java.lang.reflect.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Vector;

import org.eclipse.core.runtime.*;
import org.eclipse.update.configuration.*;
import org.eclipse.update.core.*;
import org.eclipse.update.core.model.*;
import org.eclipse.update.internal.core.*;
import org.eclipse.update.internal.core.URLEncoder;
import org.eclipse.update.internal.search.*;
import org.eclipse.update.operations.*;
import org.eclipse.update.search.*;


/**
 * Helper class for performing update related tasks, queries, etc.
 * All the methods are static and this class should be a singleton.
 */
public class UpdateUtils {
	public static final String P_UPDATE_POLICY_URL = "updatePolicyURL"; //$NON-NLS-1$

	/**
	 * Private constructor
	 */
	private UpdateUtils() {
	}
	

	public static String getPluginId() {
		return UpdateCore.getPlugin().getBundle().getSymbolicName();
	}


	public static void logException(Throwable e) {
		
		if (e instanceof InvocationTargetException) {
			e = ((InvocationTargetException) e).getTargetException();
		}

		IStatus status = null;
		if (e instanceof CoreException) {
			status = ((CoreException) e).getStatus();
		} else {
			String message = e.getMessage();
			if (message == null)
				message = e.toString();
			status = new Status(IStatus.ERROR, getPluginId(), IStatus.OK, message, e);
		}
		log(status);
	}

	public static void log(IStatus status) {
		if (status.getSeverity() != IStatus.INFO) {
			UpdateCore.getPlugin().getLog().log(status);
		} 
	}

	public static IFeature[] searchSite(String featureId, IConfiguredSite site, boolean onlyConfigured) throws CoreException {
		IFeatureReference[] references = null;

		if (onlyConfigured)
			references = site.getConfiguredFeatures();
		else
			references = site.getSite().getFeatureReferences();
		Vector result = new Vector();

		for (int i = 0; i < references.length; i++) {
			IFeature feature = references[i].getFeature(null);
			String id = feature.getVersionedIdentifier().getIdentifier();
			if (featureId.equals(id)) {
				result.add(feature);
			}
		}
		return (IFeature[]) result.toArray(new IFeature[result.size()]);
	}

	public static IFeature[] getInstalledFeatures(IFeature feature) {
		return getInstalledFeatures(feature, true);
	}

	/**
	 * 
	 * @param feature
	 * @param onlyConfigured
	 * @return IFeature[] with features matching feature ID
	 */
	public static IFeature[] getInstalledFeatures(IFeature feature, boolean onlyConfigured) {
		return getInstalledFeatures(feature.getVersionedIdentifier(), onlyConfigured);
	}
	/**
	 * @param vid
	 * @param onlyConfigured
	 * @return IFeature[] with features matching feature ID
	 */
	public static IFeature[] getInstalledFeatures(VersionedIdentifier vid, boolean onlyConfigured) {
		Vector features = new Vector();
		try {
			ILocalSite localSite = SiteManager.getLocalSite();
			IInstallConfiguration config = localSite.getCurrentConfiguration();
			IConfiguredSite[] isites = config.getConfiguredSites();
			String id = vid.getIdentifier();

			for (int i = 0; i < isites.length; i++) {
				IConfiguredSite isite = isites[i];
				IFeature[] result = UpdateUtils.searchSite(id, isite, onlyConfigured);
				for (int j = 0; j < result.length; j++) {
					IFeature installedFeature = result[j];
					features.add(installedFeature);
				}
			}
		} catch (CoreException e) {
			UpdateUtils.logException(e);
		}
		return (IFeature[]) features.toArray(new IFeature[features.size()]);
	}
	
	/**
	 * @param patch
	 * @return IFeature or null
	 */
	public static IFeature getPatchedFeature(IFeature patch) {
		IImport[] imports = patch.getImports();
		for (int i = 0; i < imports.length; i++) {
			IImport iimport = imports[i];
			if (iimport.isPatch()) {
				VersionedIdentifier patchedVid = iimport
						.getVersionedIdentifier();
				// features with matching id
				IFeature[] features = getInstalledFeatures(patchedVid, false);
				for (int f = 0; f < features.length; f++) {
					// check if version match
					if (patchedVid.equals(features[f].getVersionedIdentifier())) {
						return features[f];
					}
				}
			}
		}
		return null;
	}

	public static boolean isPatch(IFeature candidate) {
		IImport[] imports = candidate.getImports();

		for (int i = 0; i < imports.length; i++) {
			IImport iimport = imports[i];
			if (iimport.isPatch()) return true;
		}
		return false;
	}

	public static boolean isPatch(IFeature target, IFeature candidate) {
		VersionedIdentifier vid = target.getVersionedIdentifier();
		IImport[] imports = candidate.getImports();

		for (int i = 0; i < imports.length; i++) {
			IImport iimport = imports[i];
			if (iimport.isPatch()) {
				VersionedIdentifier ivid = iimport.getVersionedIdentifier();
				if (vid.equals(ivid)) {
					// Bingo.
					return true;
				}
			}
		}
		return false;
	}

	public static IInstallConfiguration getBackupConfigurationFor(IFeature feature) {
		VersionedIdentifier vid = feature.getVersionedIdentifier();
		String key = "@" + vid.getIdentifier() + "_" + vid.getVersion(); //$NON-NLS-1$ //$NON-NLS-2$
		try {
			ILocalSite lsite = SiteManager.getLocalSite();
			IInstallConfiguration[] configs = lsite.getPreservedConfigurations();
			for (int i = 0; i < configs.length; i++) {
				IInstallConfiguration config = configs[i];
				if (config.getLabel().startsWith(key))
					return config;
			}
		} catch (CoreException e) {
		}
		return null;
	}
	
	
	public static boolean hasLicense(IFeature feature) {
		IURLEntry info = feature.getLicense();
		if (info == null)
			return false;
		String licenseTxt = info.getAnnotation();
		if (licenseTxt == null)
			return false;
		return licenseTxt.trim().length() > 0;
	}
	public static boolean hasOptionalFeatures(IFeature feature) {
		try {
			IIncludedFeatureReference[] irefs = feature.getIncludedFeatureReferences();
			for (int i = 0; i < irefs.length; i++) {
				IIncludedFeatureReference iref = irefs[i];
				if (iref.isOptional())
					return true;
				// see if it has optional children
				IFeature child = getIncludedFeature( feature, iref);
				if (hasOptionalFeatures(child))
					return true;
			}
		} catch (CoreException e) {
		}
		return false;
	}

	public static IFeature getLocalFeature(
		IConfiguredSite csite,
		IFeature feature)
		throws CoreException {
		IFeatureReference[] refs = csite.getConfiguredFeatures();
		for (int i = 0; i < refs.length; i++) {
			IFeatureReference ref = refs[i];
			VersionedIdentifier refVid = ref.getVersionedIdentifier();
			if (feature.getVersionedIdentifier().equals(refVid))
				return ref.getFeature(null);
		}
		return null;
	}
	
	public static IConfiguredSite getConfigSite(
		IFeature feature,
		IInstallConfiguration config)
		throws CoreException {
		IConfiguredSite[] configSites = config.getConfiguredSites();
		for (int i = 0; i < configSites.length; i++) {
			IConfiguredSite site = configSites[i];
			if (site.getSite().equals(feature.getSite())) {
				return site;
			}
		}
		return null;
	}
	
	public static IConfiguredSite getDefaultTargetSite(
		IInstallConfiguration config,
		IInstallFeatureOperation pendingChange) {
		return getDefaultTargetSite(config, pendingChange, true);
	}

	public  static IConfiguredSite getDefaultTargetSite(
		IInstallConfiguration config,
		IInstallFeatureOperation pendingChange,
		boolean checkAffinityFeature) {
		IFeature oldFeature = pendingChange.getOldFeature();
		IFeature newFeature = pendingChange.getFeature();
		if (oldFeature != null) {
			// We should install into the same site as
			// the old feature
			try {
				return getConfigSite(oldFeature, config);
			} catch (CoreException e) {
				logException(e);
				return null;
			}
		}

		// This is a new install. Check if there is 
		// a disabled feature with the same ID
		String newFeatureID =
			newFeature.getVersionedIdentifier().getIdentifier();
		IConfiguredSite sameSite = getSiteWithFeature(config, newFeatureID);
		if (sameSite != null) {
			return sameSite;
		}

		if (checkAffinityFeature) {
			return getAffinitySite(config, newFeature);
		}
		return null;
	}
	
	public static IConfiguredSite getAffinitySite(
		IInstallConfiguration config,
		IFeature newFeature) {
		// check if the affinity feature is installed
		String affinityID = newFeature.getAffinityFeature();
		if (affinityID != null) {
			IConfiguredSite affinitySite =
				getSiteWithFeature(config, affinityID);
			if (affinitySite != null)
				return affinitySite;
		} else {
			// if this is a patch, collocate with the feature
			IFeature patchedFeature = getPatchedFeature(newFeature);
			if (patchedFeature != null)
				return getSiteWithFeature(config, patchedFeature.getVersionedIdentifier().getIdentifier());
		}
		return null;
	}

	public static IConfiguredSite getSiteWithFeature(
		IInstallConfiguration config,
		String featureID) {
		if (featureID == null)
			return null;
		IConfiguredSite[] sites = config.getConfiguredSites();
		for (int i = 0; i < sites.length; i++) {
			IConfiguredSite site = sites[i];
			IFeatureReference[] refs = site.getFeatureReferences();
			for (int j = 0; j < refs.length; j++) {
				IFeatureReference ref = refs[j];
				try {
					IFeature feature = ref.getFeature(null);
					if (featureID
						.equals(
							feature
								.getVersionedIdentifier()
								.getIdentifier())) {
						// found it
						return site;
					}
				} catch (CoreException e) {
					logException(e);
				}
			}
		}
		return null;
	}
	
	public static void collectOldFeatures(
		IFeature feature,
		IConfiguredSite targetSite,
		ArrayList result)
		throws CoreException {
		IIncludedFeatureReference[] included =
			feature.getIncludedFeatureReferences();
		for (int i = 0; i < included.length; i++) {
			IIncludedFeatureReference iref = included[i];

			IFeature ifeature;

			try {
				ifeature = iref.getFeature(null);
			} catch (CoreException e) {
				if (iref.isOptional())
					continue;
				throw e;
			}
			// find other features and unconfigure
			String id = iref.getVersionedIdentifier().getIdentifier();
			IFeature[] sameIds = UpdateUtils.searchSite(id, targetSite, true);
			for (int j = 0; j < sameIds.length; j++) {
				IFeature sameId = sameIds[j];
				// Ignore self.
				if (sameId.equals(ifeature))
					continue;
				result.add(sameId);
			}
			collectOldFeatures(ifeature, targetSite, result);
		}
	}

//
//	public static IInstallConfiguration createInstallConfiguration() throws CoreException{
//		try {
//			ILocalSite localSite = SiteManager.getLocalSite();
//			IInstallConfiguration config =
//				localSite.cloneCurrentConfiguration();
//			config.setLabel(Utilities.format(config.getCreationDate()));
//			return config;
//		} catch (CoreException e) {
//			// Let callers handle logging
//			//logException(e);
//			throw e;
//		}
//	}
	
	public static UpdateSearchRequest createNewUpdatesRequest(IFeature [] features) {
		return createNewUpdatesRequest(features, true);
	}
	
	public static UpdateSearchRequest createNewUpdatesRequest(IFeature [] features, boolean automatic) {
		UpdateSearchScope scope = new UpdateSearchScope();
		scope.setUpdateMapURL(UpdateUtils.getUpdateMapURL());
		UpdatesSearchCategory category = new UpdatesSearchCategory(automatic);
		if (features!=null)
			category.setFeatures(features);
		UpdateSearchRequest searchRequest = new UpdateSearchRequest(category, scope);
		searchRequest.addFilter(new EnvironmentFilter());
		searchRequest.addFilter(new BackLevelFilter());
		return searchRequest;
	}

	public static boolean isNestedChild(IInstallConfiguration config, IFeature feature) {
		IConfiguredSite[] csites = config.getConfiguredSites();
		try {
			for (int i = 0; csites != null && i < csites.length; i++) {
				IFeatureReference[] refs = csites[i].getConfiguredFeatures();
				for (int j = 0; refs != null && j < refs.length; j++) {
					IFeature parent = refs[j].getFeature(null);
					IFeatureReference[] children =
						parent.getIncludedFeatureReferences();
					for (int k = 0;
						children != null && k < children.length;
						k++) {
						IFeature child = children[k].getFeature(null);
						if (feature.equals(child))
							return true;
					}
				}
			}
		} catch (CoreException e) {
			// will return false
		}
		return false;
	}
	
	
	public static boolean hasObsoletePatches(IFeature feature) {
		// Check all the included features that
		// are unconfigured, and see if their patch 
		// references are better than the original.
		try {
			IFeatureReference[] irefs = feature.getIncludedFeatureReferences();
			for (int i = 0; i < irefs.length; i++) {
				IFeatureReference iref = irefs[i];
				IFeature ifeature = iref.getFeature(null);
				IConfiguredSite csite = ifeature.getSite().getCurrentConfiguredSite();
				if (!csite.isConfigured(ifeature)) {
					if (!isPatchHappy(ifeature))
						return false;
				}
			}
		} catch (CoreException e) {
			return false;
		}
		// All checks went well
		return true;
	}
	
	public static boolean isPatchHappy(IFeature feature) throws CoreException {
		// If this is a patch and it includes 
		// another patch and the included patch
		// is disabled but the feature it was declared
		// to patch is now newer (and is presumed to
		// contain the now disabled patch), and
		// the newer patched feature is enabled,
		// a 'leap of faith' assumption can be
		// made:

		// Although the included patch is disabled,
		// the feature it was designed to patch
		// is now newer and most likely contains
		// the equivalent fix and more. Consequently,
		// we can claim that the status and the error
		// icon overlay are misleading because
		// all the right plug-ins are configured.
		IImport[] imports = feature.getImports();
		IImport patchReference = null;
		for (int i = 0; i < imports.length; i++) {
			IImport iimport = imports[i];
			if (iimport.isPatch()) {
				patchReference = iimport;
				break;
			}
		}
		if (patchReference == null)
			return false;
		VersionedIdentifier refVid = patchReference.getVersionedIdentifier();

		// Find the patched feature and 
		IConfiguredSite csite = feature.getSite().getCurrentConfiguredSite();
		if (csite == null)
			return false;

		IFeatureReference[] crefs = csite.getConfiguredFeatures();
		for (int i = 0; i < crefs.length; i++) {
			IFeatureReference cref = crefs[i];
			VersionedIdentifier cvid = cref.getVersionedIdentifier();
			if (cvid.getIdentifier().equals(refVid.getIdentifier())) {
				// This is the one.
				if (cvid.getVersion().isGreaterThan(refVid.getVersion())) {
					// Bingo: we found the referenced feature
					// and its version is greater - 
					// we can assume that it contains better code
					// than the patch that referenced the
					// older version.
					return true;
				}
			}
		}
		return false;
	}

	public static URL getUpdateMapURL() {
		Preferences pref = UpdateCore.getPlugin().getPluginPreferences();
		String mapFile = pref.getString(UpdateUtils.P_UPDATE_POLICY_URL);
		if (mapFile!=null && mapFile.length()>0) {
			try {
				URL url = new URL(mapFile);
				URL resolvedURL = URLEncoder.encode(url);
				return resolvedURL;
			}
			catch (MalformedURLException e) {
				UpdateUtils.logException(e);
			}
		}
		return null;
	}
	
	/*
	 * Load the update map using the map URL found in the scope.
	 */	
	public static IStatus loadUpdatePolicy(UpdatePolicy map, URL url, IProgressMonitor monitor) throws CoreException {
		monitor.subTask(Messages.UpdateSearchRequest_loadingPolicy); 
		try {
			map.load(url, monitor);
			monitor.worked(1);
		}
		catch (CoreException e) {
			IStatus status = e.getStatus();
			if (status == null
				|| status.getCode() != ISite.SITE_ACCESS_EXCEPTION)
				throw e;
			monitor.worked(1);
			return status;
		}
		return null;
	}

	public static void downloadFeatureContent(
        IConfiguredSite targetSite,
		IFeature feature,
		IFeatureReference[] optionalChildren, // null when feature has no optional features
		IProgressMonitor progress)
		throws InstallAbortedException, CoreException {
		
		//DEBUG
		if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_INSTALL) {
			UpdateCore.debug(
				"Downloading...:" + feature.getURL().toExternalForm()); //$NON-NLS-1$
		}

		// Get source feature provider and verifier.
		// Initialize target variables.
		final IFeatureContentProvider provider =
			feature.getFeatureContentProvider();
		IPluginEntry[] targetSitePluginEntries = null;

		// determine list of plugins to install
		// find the intersection between the plugin entries already contained
		// on the target site, and plugin entries packaged in source feature
		IPluginEntry[] sourceFeaturePluginEntries = feature.getPluginEntries();

        boolean featureAlreadyInstalled = false;
        if (targetSite == null)
            targetSite = getSiteWithFeature(SiteManager.getLocalSite()
                    .getCurrentConfiguration(), ((Feature) feature)
                    .getFeatureIdentifier());
		if (targetSite == null) {
			if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_INSTALL) {
				UpdateCore.debug("The site to install in is null"); //$NON-NLS-1$
			}

			targetSitePluginEntries = new IPluginEntry[0];
		} else {
			targetSitePluginEntries = targetSite.getSite().getPluginEntries();
            featureAlreadyInstalled = UpdateUtils.getLocalFeature(targetSite,feature) != null;
		}
		IPluginEntry[] pluginsToInstall =
			UpdateManagerUtils.diff(
				sourceFeaturePluginEntries,
				targetSitePluginEntries);
		INonPluginEntry[] nonPluginsToInstall = feature.getNonPluginEntries();
		
		IFeatureReference[] children = feature.getIncludedFeatureReferences();
		if (optionalChildren != null) {
			children =
				UpdateManagerUtils.optionalChildrenToInstall(
					children,
					optionalChildren);
		}

		// make sure we have an InstallMonitor		
		InstallMonitor monitor;
		if (progress == null)
			monitor = new InstallMonitor(new NullProgressMonitor());
		else if (progress instanceof InstallMonitor)
			monitor = (InstallMonitor) progress;
		else
			monitor = new InstallMonitor(progress);

		try {
			// determine number of monitor tasks
			//   1 task1 for the feature jar (download)
			// + n tasks for plugin entries (download for each)
			// + m tasks per non-plugin data entry (download for each)
			// TODO custom install handler  + 1 task for custom non-plugin entry handling (1 for all combined)
			// + 3*x tasks for children features (3 subtasks per install)
			int taskCount =
					1
					+ pluginsToInstall.length
					+ nonPluginsToInstall.length
//				+ 1
					+ 3 * children.length;
			monitor.beginTask("", taskCount); //$NON-NLS-1$
			
			// Download feature archive(s)
			provider.getFeatureEntryArchiveReferences(monitor);
			monitorWork(monitor,1);
			
			// Download plugin archives
			for (int i = 0; i < pluginsToInstall.length; i++) {
				provider.getPluginEntryArchiveReferences(pluginsToInstall[i], monitor);
				monitorWork(monitor,1);
			}
			
			

			// Download non-plugin archives. Verification handled by optional install handler
            // Note: do not download non-plugin archives for installed features
            if (nonPluginsToInstall.length > 0) {
                // Setup optional install handler
                InstallHandlerProxy handler = null;
                if (feature.getInstallHandlerEntry()!=null)
                    handler = new InstallHandlerProxy(
                        IInstallHandler.HANDLER_ACTION_INSTALL,
                        feature,
                        feature.getInstallHandlerEntry(),
                        monitor);
            	
                if (!featureAlreadyInstalled)
                    for (int i = 0; i < nonPluginsToInstall.length; i++) {
                        if (handler==null || handler.acceptNonPluginData(nonPluginsToInstall[i]))
                        	provider.getNonPluginEntryArchiveReferences(
                                nonPluginsToInstall[i], monitor);
                        monitorWork(monitor, 1);
                    }
                else
                    monitorWork(monitor, nonPluginsToInstall.length);
            }
           
			// Download child features
			for (int i = 0; i < children.length; i++) {
				IFeature childFeature = null;
				try {
					childFeature = children[i].getFeature(null);
				} catch (CoreException e) {
					UpdateCore.warn(null, e);
				}
				if (childFeature != null) {
					SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, 3);
					downloadFeatureContent(targetSite, childFeature, optionalChildren, subMonitor);
				}
			}
		} finally {
			if (monitor != null)
				monitor.done();
		}
	}
	
	private static void monitorWork(IProgressMonitor monitor, int tick)
	throws CoreException {
	if (monitor != null) {
		monitor.worked(tick);
		if (monitor.isCanceled()) {
			String msg = "download cancelled";//Policy.bind("Feature.InstallationCancelled"); //$NON-NLS-1$
			throw new InstallAbortedException(msg, null);
		}
	}
}
	public static IFeature getIncludedFeature(IFeature feature, IFeatureReference iref) throws CoreException {
		IFeature ifeature = null;
		if (feature.getSite() instanceof ExtendedSite) {
			ifeature = ((ExtendedSite)feature.getSite()).getLiteFeature(iref.getVersionedIdentifier());
		}
		if (ifeature == null) {
			ifeature = iref.getFeature(new NullProgressMonitor());
		}
		return ifeature;
	}
}
