/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.update.internal.core;
import java.io.*;
import java.util.*;

import org.eclipse.core.runtime.*;
import org.eclipse.update.core.*;
import org.eclipse.update.core.model.*;

/**
 * @author birsan
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
/**
 * 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(Policy.bind("SiteFile.Removing") + feature.getLabel(), pluginsToRemove.length + 1);	//$NON-NLS-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(Policy.bind("SiteFile.featureNotRemoved", feature.getVersionedIdentifier().toString()), null); //$NON-NLS-1$ //$NON-NLS-2$
			} 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(Policy.bind("SiteFile.CannotRemoveFeature", feature.getVersionedIdentifier().getIdentifier(), getURL().toExternalForm()), e);	//$NON-NLS-1$
					}
				}
				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$
				}
				if (childFeature != null)
					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(Policy.bind("InstallHandler.error", feature.getLabel()), originalException); //$NON-NLS-1$
			if (newException != null)
				throw Utilities.newCoreException(Policy.bind("InstallHandler.error", feature.getLabel()), newException);//$NON-NLS-1$
		}
	}

	/**
	 * 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;
		IPluginEntry[] entriesToInstall = feature.getPluginEntries();
		IPluginEntry[] siteEntries = this.getPluginEntries();
		entriesToInstall = UpdateManagerUtils.diff(entriesToInstall, siteEntries);
		//[18355]
		INonPluginEntry[] nonPluginEntriesToInstall = feature.getNonPluginEntries();

		try {
			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 = children[i].getFeature(null);
				if (currentFeature != null) {
					pluginsToInstall.addAll(Arrays.asList(currentFeature.getPluginEntries()));
				}
			}

			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();

			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(Policy.bind("SiteFile.pluginNotRemoved", pluginEntry.getVersionedIdentifier().toString()), null); //$NON-NLS-1$ //$NON-NLS-2$
			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(Policy.bind("SiteFile.CannotRemovePlugin", pluginEntry.getVersionedIdentifier().toString(), getURL().toExternalForm()), e);//$NON-NLS-1$
			}
		}
		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(Policy.bind("SiteFile.CannotRemoveFeature", feature.getVersionedIdentifier().getIdentifier(), getURL().toExternalForm()), e); //$NON-NLS-1$
				}
			}
			// 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(Policy.bind("SiteFile.CannotRemovePlugin", pluginsToRemove[i].getVersionedIdentifier().toString(), getURL().toExternalForm()), e); //$NON-NLS-1$
					}
				}
			}
		}

		// 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);
		}
	}

}
