/*******************************************************************************
 * Copyright (c) 2000, 2005 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.update.internal.core;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.osgi.util.NLS;
import org.eclipse.update.core.ContentReference;
import org.eclipse.update.core.IFeature;
import org.eclipse.update.core.IFeatureContentConsumer;
import org.eclipse.update.core.IFeatureFactory;
import org.eclipse.update.core.IFeatureReference;
import org.eclipse.update.core.IInstallHandler;
import org.eclipse.update.core.INonPluginEntry;
import org.eclipse.update.core.IPluginEntry;
import org.eclipse.update.core.ISite;
import org.eclipse.update.core.ISiteFeatureReference;
import org.eclipse.update.core.IVerificationListener;
import org.eclipse.update.core.IVerifier;
import org.eclipse.update.core.InstallMonitor;
import org.eclipse.update.core.Site;
import org.eclipse.update.core.Utilities;
import org.eclipse.update.core.model.ContentEntryModel;
import org.eclipse.update.core.model.FeatureModel;
import org.eclipse.update.core.model.FeatureReferenceModel;
import org.eclipse.update.core.model.InstallAbortedException;
import org.eclipse.update.internal.operations.UpdateUtils;


/**
 * Site on the File System
 */
public class SiteFile extends Site {

	/**
	 * plugin entries 
	 */
	private List pluginEntries = new ArrayList(0);

	/**
	 * 
	 */
	public ISiteContentConsumer createSiteContentConsumer(IFeature targetFeature) throws CoreException {
		SiteFileContentConsumer consumer = new SiteFileContentConsumer(targetFeature);
		consumer.setSite(this);
		return consumer;
	}

	/**
	 */
	public String getDefaultPackagedFeatureType() {
		return DEFAULT_INSTALLED_FEATURE_TYPE;
	}

	/*
	 * @see ISite#install(IFeature, IVerifier, IProgressMonitor)
	 */
	public IFeatureReference install(IFeature sourceFeature, IVerificationListener verificationListener, IProgressMonitor progress) throws CoreException {
		return install(sourceFeature,null,verificationListener,progress);
	}

	/*
	 * @see ISite#install(IFeature, IVerifier, IProgressMonitor)
	 */
	public IFeatureReference install(IFeature sourceFeature, IFeatureReference[] optionalfeatures, IVerificationListener verificationListener, IProgressMonitor progress) throws CoreException {

		if (sourceFeature == null)
			return null;

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

		// create new executable feature and install source content into it
		IFeature localFeature = createExecutableFeature(sourceFeature);

		IFeatureReference localFeatureReference = null;
		localFeatureReference = sourceFeature.install(localFeature, optionalfeatures, verificationListener, monitor);

		return localFeatureReference;
	}

	/*
	 * @see ISite#install(IFeature,IFeatureContentConsumer, IVerifier,IVerificationLIstener, IProgressMonitor)
	 */
	public IFeatureReference install(IFeature sourceFeature, IFeatureReference[] optionalfeatures, IFeatureContentConsumer parentContentConsumer, IVerifier parentVerifier, IVerificationListener verificationListener, IProgressMonitor progress)
		throws InstallAbortedException, CoreException {

		if (sourceFeature == null)
			return null;

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

		// create new executable feature and install source content into it
		IFeature localFeature = createExecutableFeature(sourceFeature);
		parentContentConsumer.addChild(localFeature);

		// set the verifier
		IVerifier vr = sourceFeature.getFeatureContentProvider().getVerifier();
		if (vr != null)
			vr.setParent(parentVerifier);

		IFeatureReference localFeatureReference = null;
		localFeatureReference = sourceFeature.install(localFeature, optionalfeatures, verificationListener, monitor);

		return localFeatureReference;
	}

	/*
	 * @see ISite#remove(IFeature, IProgressMonitor)
	 */
	public void remove(IFeature feature, IProgressMonitor progress) throws CoreException {

		if (feature == null) {
			UpdateCore.warn("Feature to remove is null"); //$NON-NLS-1$
			return;
		}
		
		ErrorRecoveryLog recoveryLog = ErrorRecoveryLog.getLog();

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

		// Setup optional install handler
		InstallHandlerProxy handler = new InstallHandlerProxy(IInstallHandler.HANDLER_ACTION_UNINSTALL, feature, feature.getInstallHandlerEntry(), monitor);
		boolean success = false;
		Throwable originalException = null;

		try {

			// start log
			recoveryLog.open(ErrorRecoveryLog.START_REMOVE_LOG);

			aboutToRemove(feature);

			// log files have been downloaded
			recoveryLog.append(ErrorRecoveryLog.END_ABOUT_REMOVE);

			handler.uninstallInitiated();

			// remove the feature and the plugins if they are not used and not activated
			// get the plugins from the feature
			IPluginEntry[] pluginsToRemove = getPluginEntriesOnlyReferencedBy(feature);

			if (monitor != null) {
				monitor.beginTask(Messages.SiteFile_Removing + feature.getLabel(), pluginsToRemove.length + 1);	
			}

			// remove feature reference from the site
			ISiteFeatureReference[] featureReferences = getFeatureReferences();
			if (featureReferences != null) {
				for (int indexRef = 0; indexRef < featureReferences.length; indexRef++) {
					IFeatureReference element = featureReferences[indexRef];
					if (element.getVersionedIdentifier().equals(feature.getVersionedIdentifier())) {
						removeFeatureReferenceModel((FeatureReferenceModel) element);
						break;
					}
				}
			}

			if (InstallRegistry.getInstance().get("feature_"+feature.getVersionedIdentifier()) == null) { //$NON-NLS-1$
				UpdateCore.log(NLS.bind(Messages.SiteFile_featureNotRemoved, (new String[] { feature.getVersionedIdentifier().toString() })), null);
			} else {
				// remove the feature content
				ContentReference[] references = feature.getFeatureContentProvider().getFeatureEntryArchiveReferences(monitor);
				for (int i = 0; i < references.length; i++) {
					try {
						UpdateManagerUtils.removeFromFileSystem(references[i].asFile());
						if (monitor != null)
							monitor.worked(1);
					} catch (IOException e) {
						throw Utilities.newCoreException(NLS.bind(Messages.SiteFile_CannotRemoveFeature, (new String[] { feature.getVersionedIdentifier().getIdentifier(), getURL().toExternalForm() })), e);
					}
				}
				InstallRegistry.unregisterFeature(feature);
			}

			//finds the contentReferences for an IPluginEntry
			// and remove it
			for (int i = 0; i < pluginsToRemove.length; i++) {
				remove(feature, pluginsToRemove[i], monitor);
			}

			// remove any children feature
			IFeatureReference[] childrenRef = feature.getIncludedFeatureReferences();
			for (int i = 0; i < childrenRef.length; i++) {
				IFeature childFeature = null;
				try {
					childFeature = childrenRef[i].getFeature(null);
				} catch (CoreException e) {
					UpdateCore.warn("Unable to retrieve feature to remove for:" + childrenRef[i]); //$NON-NLS-1$
				}
                // do not remove nested feature if configured (i.e. used by another configured feature)
				if (childFeature != null && !getCurrentConfiguredSite().isConfigured(childFeature))
					remove(childrenRef[i].getFeature(null), monitor);
			}

			// remove the feature from the site cache
			removeFeatureFromCache(feature.getURL());
			
			handler.completeUninstall();

			success = true;
		} catch (Throwable t) {
			originalException = t;
		} finally {
			Throwable newException = null;
			try {
				if (success) {
					// close the log
					recoveryLog.close(ErrorRecoveryLog.END_REMOVE_LOG);
					recoveryLog.delete();
				} else {
					recoveryLog.close(ErrorRecoveryLog.END_REMOVE_LOG);
				}
				handler.uninstallCompleted(success);
			} catch (Throwable t) {
				newException = t;
			}
			if (originalException != null) // original exception wins
				throw Utilities.newCoreException(NLS.bind(Messages.InstallHandler_error, (new String[] { feature.getLabel() })), originalException);
			if (newException != null)
				throw Utilities.newCoreException(NLS.bind(Messages.InstallHandler_error, (new String[] { feature.getLabel() })), newException);
		}
	}

	/**
	 * returns the download size
	 * of the feature to be installed on the site.
	 * If the site is <code>null</code> returns the maximum size
	 * 
	 * If one plug-in entry has an unknown size.
	 * then the download size is unknown.
	 * 
	 */
	public long getDownloadSizeFor(IFeature feature) {
		long result = 0;
		//[132029]
		//IPluginEntry[] entriesToInstall = feature.getPluginEntries();
		//IPluginEntry[] siteEntries = this.getPluginEntries();
		//entriesToInstall = UpdateManagerUtils.diff(entriesToInstall, siteEntries);
		//[18355]
		//INonPluginEntry[] nonPluginEntriesToInstall = feature.getNonPluginEntries();

		try {
			//[132029]
			//result = feature.getFeatureContentProvider().getDownloadSizeFor(entriesToInstall, nonPluginEntriesToInstall);
			IFeatureReference[] children = feature.getIncludedFeatureReferences();
			IFeature currentFeature = null;
			for (int i = 0; i < children.length; i++) {
				currentFeature = UpdateUtils.getIncludedFeature(feature, children[i]);
				if (currentFeature != null) {
					result += getDownloadSizeFor(currentFeature);
					if(result == ContentEntryModel.UNKNOWN_SIZE)
						return result;
				}
			}

			IPluginEntry[] entriesToInstall = feature.getPluginEntries();
			IPluginEntry[] siteEntries = this.getPluginEntries();
			entriesToInstall = UpdateManagerUtils.diff(entriesToInstall, siteEntries);
			//[18355]
			   INonPluginEntry[] nonPluginEntriesToInstall = feature.getNonPluginEntries();

			 result += feature.getFeatureContentProvider().getDownloadSizeFor(entriesToInstall, nonPluginEntriesToInstall);
		} catch (CoreException e) {
			UpdateCore.warn(null, e);
			result = ContentEntryModel.UNKNOWN_SIZE;
		}
		return result;
	}

	/**
	 * returns the download size
	 * of the feature to be installed on the site.
	 * If the site is <code>null</code> returns the maximum size
	 * 
	 * If one plug-in entry has an unknown size.
	 * then the download size is unknown.
	 * 
	 * @see ISite#getDownloadSizeFor(IFeature)
	 * 
	 */
	public long getInstallSizeFor(IFeature feature) {
		long result = 0;

		try {
			List pluginsToInstall = new ArrayList();

			// get all the plugins [17304]
			pluginsToInstall.addAll(Arrays.asList(feature.getPluginEntries()));
			IFeatureReference[] children = feature.getIncludedFeatureReferences();
			IFeature currentFeature = null;
			for (int i = 0; i < children.length; i++) {
				currentFeature = UpdateUtils.getIncludedFeature(feature, children[i]);
				if (currentFeature != null) {
					//[132029]
					//pluginsToInstall.addAll(Arrays.asList(currentFeature.getPluginEntries()));
					result += getInstallSizeFor(currentFeature);
					if (result == ContentEntryModel.UNKNOWN_SIZE)
						return result;
				}
			}

			IPluginEntry[] entriesToInstall = new IPluginEntry[0];
			if (pluginsToInstall.size() > 0) {
				entriesToInstall = new IPluginEntry[pluginsToInstall.size()];
				pluginsToInstall.toArray(entriesToInstall);
			}

			IPluginEntry[] siteEntries = this.getPluginEntries();
			entriesToInstall = UpdateManagerUtils.diff(entriesToInstall, siteEntries);

			//[18355]
			INonPluginEntry[] nonPluginEntriesToInstall = feature.getNonPluginEntries();
			
			//[132029]
			//result = feature.getFeatureContentProvider().getInstallSizeFor(entriesToInstall, nonPluginEntriesToInstall);
			result += feature.getFeatureContentProvider().getInstallSizeFor(entriesToInstall, nonPluginEntriesToInstall);
		} catch (CoreException e) {
			UpdateCore.warn(null, e);
			result = ContentEntryModel.UNKNOWN_SIZE;
		}

		return result;
	}

	/**
	 * Adds a plugin entry 
	 * Either from parsing the file system or 
	 * installing a feature
	 * 
	 * We cannot figure out the list of plugins by reading the Site.xml as
	 * the archives tag are optionals
	 */
	public void addPluginEntry(IPluginEntry pluginEntry) {
		pluginEntries.add(pluginEntry);
	}

	public IPluginEntry[] getPluginEntries() {
		IPluginEntry[] result = new IPluginEntry[0];
		if (!(pluginEntries == null || pluginEntries.isEmpty())) {
			result = new IPluginEntry[pluginEntries.size()];
			pluginEntries.toArray(result);
		}
		return result;
	}


	public int getPluginEntryCount() {
		return getPluginEntries().length;
	}

	/**
	 * 
	 */
	private IFeature createExecutableFeature(IFeature sourceFeature) throws CoreException {
		IFeature result = null;
		IFeatureFactory factory = FeatureTypeFactory.getInstance().getFactory(DEFAULT_INSTALLED_FEATURE_TYPE);
		result = factory.createFeature(/*URL*/null, this, null);

		// at least set the version identifier to be the same
		 ((FeatureModel) result).setFeatureIdentifier(sourceFeature.getVersionedIdentifier().getIdentifier());
		((FeatureModel) result).setFeatureVersion(sourceFeature.getVersionedIdentifier().getVersion().toString());
		return result;
	}

	/**
	 * 
	 */
	private void remove(IFeature feature, IPluginEntry pluginEntry, InstallMonitor monitor) throws CoreException {

		if (pluginEntry == null)
			return;
			
		if (InstallRegistry.getInstance().get("plugin_"+pluginEntry.getVersionedIdentifier()) == null) { //$NON-NLS-1$
			UpdateCore.log(NLS.bind(Messages.SiteFile_pluginNotRemoved, (new String[] { pluginEntry.getVersionedIdentifier().toString() })), null);
			return; 
		}

		ContentReference[] references = feature.getFeatureContentProvider().getPluginEntryArchiveReferences(pluginEntry, monitor);
		for (int i = 0; i < references.length; i++) {
			try {
				UpdateManagerUtils.removeFromFileSystem(references[i].asFile());
				if (monitor != null)
					monitor.worked(1);
			} catch (IOException e) {
				throw Utilities.newCoreException(NLS.bind(Messages.SiteFile_CannotRemovePlugin, (new String[] { pluginEntry.getVersionedIdentifier().toString(), getURL().toExternalForm() })), e);
			}
		}
		pluginEntries.remove(pluginEntry);
		InstallRegistry.unregisterPlugin(pluginEntry);
	}

	/*
	 * 
	 */
	private void aboutToRemove(IFeature feature) throws CoreException {

		ErrorRecoveryLog recoveryLog = ErrorRecoveryLog.getLog();
		// if the recovery is not turned on
		if (!ErrorRecoveryLog.RECOVERY_ON)
			return;

		//logFeature
		if (feature != null) {
					
			// log feature URL
			ContentReference[] references = feature.getFeatureContentProvider().getFeatureEntryArchiveReferences(null);
			for (int i = 0; i < references.length; i++) {
				try {
					recoveryLog.appendPath(ErrorRecoveryLog.FEATURE_ENTRY, references[i].asFile().getAbsolutePath());
				} catch (IOException e) {
					String id = UpdateCore.getPlugin().getBundle().getSymbolicName();
					throw Utilities.newCoreException(NLS.bind(Messages.SiteFile_CannotRemoveFeature, (new String[] { feature.getVersionedIdentifier().getIdentifier(), getURL().toExternalForm() })), e);
				}
			}
			// log pluginEntry URL
			IPluginEntry[] pluginsToRemove = getPluginEntriesOnlyReferencedBy(feature);
			for (int i = 0; i < pluginsToRemove.length; i++) {
				references = feature.getFeatureContentProvider().getPluginEntryArchiveReferences(pluginsToRemove[i], null);
				for (int j = 0; j < references.length; j++) {
					try {
						recoveryLog.appendPath(ErrorRecoveryLog.BUNDLE_JAR_ENTRY, references[j].asFile().getAbsolutePath());
					} catch (IOException e) {
						throw Utilities.newCoreException(NLS.bind(Messages.SiteFile_CannotRemovePlugin, (new String[] { pluginsToRemove[i].getVersionedIdentifier().toString(), getURL().toExternalForm() })), e);
					}
				}
			}
		}

		// call recursively for each children	 
		IFeatureReference[] childrenRef = feature.getIncludedFeatureReferences();
		IFeature childFeature = null;
		for (int i = 0; i < childrenRef.length; i++) {
			try {
				childFeature = childrenRef[i].getFeature(null);
			} catch (CoreException e) {
				UpdateCore.warn("Unable to retrieve feature to remove for:" + childrenRef[i]); //$NON-NLS-1$
			}
			aboutToRemove(childFeature);
		}
	}

}
