/*******************************************************************************
 * Copyright (c) 2007, 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 implementation and ideas 
 ******************************************************************************/
package org.eclipse.equinox.internal.provisional.p2.directorywatcher;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
import org.eclipse.equinox.internal.p2.metadata.generator.features.FeatureParser;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.*;
import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
import org.eclipse.equinox.internal.provisional.p2.core.eventbus.IProvisioningEventBus;
import org.eclipse.equinox.internal.provisional.p2.core.repository.IRepository;
import org.eclipse.equinox.internal.provisional.p2.core.repository.RepositoryEvent;
import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey;
import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
import org.eclipse.equinox.internal.provisional.p2.metadata.query.InstallableUnitQuery;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
import org.eclipse.equinox.internal.provisional.p2.query.Collector;
import org.eclipse.equinox.internal.provisional.p2.query.Query;
import org.eclipse.osgi.service.resolver.*;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

public class RepositoryListener extends DirectoryChangeListener {
	private static final String ARTIFACT_FOLDER = "artifact.folder"; //$NON-NLS-1$
	private static final String ARTIFACT_REFERENCE = "artifact.reference"; //$NON-NLS-1$
	private static final String FILE_LAST_MODIFIED = "file.lastModified"; //$NON-NLS-1$
	private static final String FILE_NAME = "file.name"; //$NON-NLS-1$
	private final IMetadataRepository metadataRepository;
	private final IArtifactRepository artifactRepository;
	private final BundleDescriptionFactory bundleDescriptionFactory;
	private final Map currentFiles = new HashMap();

	private Collection polledSeenFiles = new HashSet();
	private Collection polledIUsToAdd = new ArrayList();
	private Collection polledArtifactsToAdd = new ArrayList();

	/**
	 * Create a repository listener that watches the specified folder and generates repositories
	 * for its content.
	 * @param context the bundle context
	 * @param repositoryName the repository name to use for the repository
	 * @param repositoryFolder the target folder for the repository, or <code>null</code> if a folder based on the
	 * bundle's data location should be used.
	 * @param hidden <code>true</code> if the repository should be hidden, <code>false</code> if not.
	 */
	public RepositoryListener(BundleContext context, String repositoryName, File repositoryFolder, boolean hidden) {
		File stateDir;
		if (repositoryFolder == null) {
			String stateDirName = "listener_" + repositoryName.hashCode(); //$NON-NLS-1$
			stateDir = context.getDataFile(stateDirName);
			stateDir.mkdirs();
		} else {
			stateDir = repositoryFolder;
		}

		URL stateDirURL;
		try {
			stateDirURL = stateDir.toURL();
		} catch (MalformedURLException e) {
			throw new IllegalStateException(e.getMessage());
		}

		metadataRepository = initializeMetadataRepository(context, repositoryName, stateDirURL, hidden);
		artifactRepository = initializeArtifactRepository(context, repositoryName, stateDirURL, hidden);
		bundleDescriptionFactory = initializeBundleDescriptionFactory(context);
		synchronizeCurrentFiles();
	}

	public RepositoryListener(BundleContext context, IMetadataRepository metadataRepository, IArtifactRepository artifactRepository) {
		this.artifactRepository = artifactRepository;
		this.metadataRepository = metadataRepository;
		bundleDescriptionFactory = initializeBundleDescriptionFactory(context);
		synchronizeCurrentFiles();
	}

	/**
	 * Broadcast events for any discovery sites associated with the feature
	 * so the repository managers add them to their list of known repositories.
	 */
	private void publishSites(Feature feature) {
		IProvisioningEventBus bus = (IProvisioningEventBus) ServiceHelper.getService(Activator.getContext(), IProvisioningEventBus.SERVICE_NAME);
		if (bus == null)
			return;
		URLEntry[] discoverySites = feature.getDiscoverySites();
		for (int i = 0; i < discoverySites.length; i++)
			publishSite(feature, bus, discoverySites[i].getURL(), false);
		String updateSite = feature.getUpdateSiteURL();
		if (updateSite != null)
			publishSite(feature, bus, updateSite, true);
	}

	/**
	 * Broadcast a discovery event for the given repository location.
	 */
	private void publishSite(Feature feature, IProvisioningEventBus bus, String locationString, boolean isEnabled) {
		try {
			URL location = new URL(locationString);
			bus.publishEvent(new RepositoryEvent(location, IRepository.TYPE_METADATA, RepositoryEvent.DISCOVERED, isEnabled));
			bus.publishEvent(new RepositoryEvent(location, IRepository.TYPE_ARTIFACT, RepositoryEvent.DISCOVERED, isEnabled));
		} catch (MalformedURLException e) {
			LogHelper.log(new Status(IStatus.WARNING, Activator.ID, "Feature references invalid site: " + feature.getId(), e)); //$NON-NLS-1$
		}
	}

	private BundleDescriptionFactory initializeBundleDescriptionFactory(BundleContext context) {
		ServiceReference reference = context.getServiceReference(PlatformAdmin.class.getName());
		if (reference == null)
			throw new IllegalStateException(Messages.platformadmin_not_registered);
		PlatformAdmin platformAdmin = (PlatformAdmin) context.getService(reference);
		if (platformAdmin == null)
			throw new IllegalStateException(Messages.platformadmin_not_registered);

		try {
			StateObjectFactory stateObjectFactory = platformAdmin.getFactory();
			return new BundleDescriptionFactory(stateObjectFactory, null);
		} finally {
			context.ungetService(reference);
		}
	}

	private IArtifactRepository initializeArtifactRepository(BundleContext context, String repositoryName, URL stateDirURL, boolean hidden) {
		ServiceReference reference = context.getServiceReference(IArtifactRepositoryManager.class.getName());
		IArtifactRepositoryManager manager = null;
		if (reference != null)
			manager = (IArtifactRepositoryManager) context.getService(reference);
		if (manager == null)
			throw new IllegalStateException(Messages.artifact_repo_manager_not_registered);

		try {
			try {
				return manager.loadRepository(stateDirURL, null);
			} catch (ProvisionException e) {
				//fall through and create a new repository
			}
			try {
				String name = repositoryName;
				Map properties = new HashMap(1);
				if (hidden) {
					properties.put(IRepository.PROP_SYSTEM, Boolean.TRUE.toString());
					name = "artifact listener " + repositoryName; //$NON-NLS-1$
				}
				return manager.createRepository(stateDirURL, name, IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
			} catch (ProvisionException e) {
				LogHelper.log(e);
				throw new IllegalStateException(NLS.bind(Messages.failed_create_artifact_repo, stateDirURL));
			}
		} finally {
			context.ungetService(reference);
		}
	}

	private IMetadataRepository initializeMetadataRepository(BundleContext context, String repositoryName, URL stateDirURL, boolean hidden) {
		ServiceReference reference = context.getServiceReference(IMetadataRepositoryManager.class.getName());
		IMetadataRepositoryManager manager = null;
		if (reference != null)
			manager = (IMetadataRepositoryManager) context.getService(reference);
		if (manager == null)
			throw new IllegalStateException(Messages.metadata_repo_manager_not_registered);

		try {
			try {
				return manager.loadRepository(stateDirURL, null);
			} catch (ProvisionException e) {
				//fall through and create new repository
			}
			String name = repositoryName;
			Map properties = new HashMap(1);
			if (hidden) {
				properties.put(IRepository.PROP_SYSTEM, Boolean.TRUE.toString());
				name = "metadata listener " + repositoryName; //$NON-NLS-1$
			}
			return manager.createRepository(stateDirURL, name, IMetadataRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
		} catch (ProvisionException e) {
			LogHelper.log(e);
			throw new IllegalStateException(NLS.bind(Messages.failed_create_metadata_repo, stateDirURL));
		} finally {
			context.ungetService(reference);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.IDirectoryChangeListener#added(java.io.File)
	 */
	public boolean added(File file) {
		return process(file);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.IDirectoryChangeListener#changed(java.io.File)
	 */
	public boolean changed(File file) {
		// this sequence will trigger removal and then addition during stopPoll
		polledSeenFiles.remove(file);
		return process(file);
	}

	public boolean removed(File file) {
		// this file will get removed in stopPoll
		return currentFiles.containsKey(file);
	}

	private boolean process(File file) {
		boolean isDirectory = file.isDirectory();
		// is it a feature ?
		if (isDirectory && file.getParentFile() != null && file.getParentFile().getName().equals("features") && new File(file, "feature.xml").exists()) //$NON-NLS-1$ //$NON-NLS-2$)
			return processFeature(file);

		// is it a bundle ?
		if (isDirectory || file.getName().endsWith(".jar")) //$NON-NLS-1$
			return processBundle(file, isDirectory);

		return false;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.IDirectoryChangeListener#removed(java.io.File)
	 */

	private boolean processBundle(File file, boolean isDirectory) {
		BundleDescription bundleDescription = bundleDescriptionFactory.getBundleDescription(file);
		if (bundleDescription == null)
			return false;

		String fileName = file.getAbsolutePath();
		String lastModified = Long.toString(file.lastModified());

		// Add Bundle IU
		Properties props = new Properties();
		props.setProperty(FILE_NAME, fileName);
		props.setProperty(FILE_LAST_MODIFIED, lastModified);

		IArtifactKey key = MetadataGeneratorHelper.createBundleArtifactKey(bundleDescription.getSymbolicName(), bundleDescription.getVersion().toString());
		IInstallableUnit[] ius = MetadataGeneratorHelper.createEclipseIU(bundleDescription, (Map) bundleDescription.getUserObject(), isDirectory, key, props);

		// see bug 222370
		// we only want to return the bundle IU so must exclude all fragment IUs
		IInstallableUnit bundleIU = null;
		for (int i = 0; i < ius.length; i++) {
			if (!ius[i].isFragment()) {
				bundleIU = ius[i];
				break;
			}
		}

		if (bundleIU == null) {
			if (ius.length == 0)
				return false;
			throw new IllegalStateException(Messages.multiple_bundle_ius);
		}
		polledIUsToAdd.add(bundleIU);

		// Add Bundle Artifact
		ArtifactDescriptor descriptor = new ArtifactDescriptor(MetadataGeneratorHelper.createArtifactDescriptor(key, file, true, false));
		try {
			descriptor.setRepositoryProperty(ARTIFACT_REFERENCE, file.toURL().toExternalForm());
		} catch (MalformedURLException e) {
			// unexpected
			e.printStackTrace();
			return false;
		}
		if (isDirectory)
			descriptor.setRepositoryProperty(ARTIFACT_FOLDER, Boolean.TRUE.toString());
		descriptor.setRepositoryProperty(FILE_NAME, fileName);
		descriptor.setRepositoryProperty(FILE_LAST_MODIFIED, lastModified);

		polledArtifactsToAdd.add(descriptor);
		return true;
	}

	private boolean processFeature(File file) {
		FeatureParser parser = new FeatureParser();
		Feature feature = parser.parse(file);
		if (feature == null)
			return false;

		publishSites(feature);

		String fileName = file.getAbsolutePath();
		String lastModified = Long.toString(file.lastModified());

		// Add Feature IUs
		Properties props = new Properties();
		props.setProperty(FILE_NAME, fileName);
		props.setProperty(FILE_LAST_MODIFIED, lastModified);

		IInstallableUnit featureIU = MetadataGeneratorHelper.createFeatureJarIU(feature, true, props);
		IInstallableUnit groupIU = MetadataGeneratorHelper.createGroupIU(feature, featureIU, props);

		polledIUsToAdd.add(featureIU);
		polledIUsToAdd.add(groupIU);

		// Add Feature Artifact
		IArtifactKey featureKey = MetadataGeneratorHelper.createFeatureArtifactKey(feature.getId(), feature.getVersion());
		ArtifactDescriptor descriptor = new ArtifactDescriptor(featureKey);

		try {
			descriptor.setRepositoryProperty(ARTIFACT_REFERENCE, file.toURL().toExternalForm());
		} catch (MalformedURLException e) {
			// unexpected
			e.printStackTrace();
			return false;
		}
		descriptor.setRepositoryProperty(ARTIFACT_FOLDER, Boolean.TRUE.toString());
		descriptor.setRepositoryProperty(FILE_NAME, fileName);
		descriptor.setRepositoryProperty(FILE_LAST_MODIFIED, lastModified);

		polledArtifactsToAdd.add(descriptor);
		return true;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryChangeListener#isInterested(java.io.File)
	 */
	public boolean isInterested(File file) {
		return true;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.IDirectoryChangeListener#getSeenFile(java.io.File)
	 */
	public Long getSeenFile(File file) {
		Long lastSeen = (Long) currentFiles.get(file);
		if (lastSeen != null)
			polledSeenFiles.add(file);
		return lastSeen;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.IDirectoryChangeListener#startPoll()
	 */
	public void startPoll() {
		// do nothing
	}

	/* (non-Javadoc)
	 * @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.IDirectoryChangeListener#stopPoll()
	 */
	public void stopPoll() {
		final Set removedFiles = new HashSet(currentFiles.keySet());
		removedFiles.removeAll(polledSeenFiles);
		polledSeenFiles.clear();

		if (removedFiles.isEmpty() && polledIUsToAdd.isEmpty() && polledArtifactsToAdd.isEmpty())
			return;

		if (metadataRepository != null)
			synchronizeMetadataRepository(removedFiles);

		if (artifactRepository != null)
			synchronizeArtifactRepository(removedFiles);

		synchronizeCurrentFiles();

		polledIUsToAdd.clear();
		polledArtifactsToAdd.clear();
	}

	private void synchronizeMetadataRepository(final Set removedFiles) {
		Query removeQuery = new Query() {
			public boolean isMatch(Object candidate) {
				if (!(candidate instanceof IInstallableUnit))
					return false;
				IInstallableUnit iu = (IInstallableUnit) candidate;
				File iuFile = new File(iu.getProperty(FILE_NAME));
				return removedFiles.contains(iuFile);
			}
		};
		metadataRepository.removeInstallableUnits(removeQuery, null);

		if (!polledIUsToAdd.isEmpty())
			metadataRepository.addInstallableUnits((IInstallableUnit[]) polledIUsToAdd.toArray(new IInstallableUnit[polledIUsToAdd.size()]));
	}

	private void synchronizeArtifactRepository(final Set removedFiles) {
		final List keys = new ArrayList(Arrays.asList(artifactRepository.getArtifactKeys()));
		for (Iterator it = keys.iterator(); it.hasNext();) {
			IArtifactKey key = (IArtifactKey) it.next();
			IArtifactDescriptor[] descriptors = artifactRepository.getArtifactDescriptors(key);
			for (int i = 0; i < descriptors.length; i++) {
				ArtifactDescriptor descriptor = (ArtifactDescriptor) descriptors[i];
				File artifactFile = new File(descriptor.getRepositoryProperty(FILE_NAME));
				if (removedFiles.contains(artifactFile))
					artifactRepository.removeDescriptor(descriptor);
			}
		}

		if (!polledArtifactsToAdd.isEmpty())
			artifactRepository.addDescriptors((IArtifactDescriptor[]) polledArtifactsToAdd.toArray(new IArtifactDescriptor[polledArtifactsToAdd.size()]));
	}

	private void synchronizeCurrentFiles() {
		currentFiles.clear();
		if (metadataRepository != null) {
			Collector ius = metadataRepository.query(InstallableUnitQuery.ANY, new Collector(), null);
			for (Iterator it = ius.iterator(); it.hasNext();) {
				IInstallableUnit iu = (IInstallableUnit) it.next();
				File iuFile = new File(iu.getProperty(FILE_NAME));
				Long iuLastModified = new Long(iu.getProperty(FILE_LAST_MODIFIED));
				currentFiles.put(iuFile, iuLastModified);
			}
		}

		if (artifactRepository != null) {
			final List keys = new ArrayList(Arrays.asList(artifactRepository.getArtifactKeys()));
			for (Iterator it = keys.iterator(); it.hasNext();) {
				IArtifactKey key = (IArtifactKey) it.next();
				IArtifactDescriptor[] descriptors = artifactRepository.getArtifactDescriptors(key);
				for (int i = 0; i < descriptors.length; i++) {
					ArtifactDescriptor descriptor = (ArtifactDescriptor) descriptors[i];
					File artifactFile = new File(descriptor.getRepositoryProperty(FILE_NAME));
					Long artifactLastModified = new Long(descriptor.getRepositoryProperty(FILE_LAST_MODIFIED));
					currentFiles.put(artifactFile, artifactLastModified);
				}
			}
		}
	}

	public IMetadataRepository getMetadataRepository() {
		return metadataRepository;
	}

	public IArtifactRepository getArtifactRepository() {
		return artifactRepository;
	}
}
