/*******************************************************************************
 *  Copyright (c) 2007, 2009 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 
 *   Code 9 - ongoing development
 *******************************************************************************/
package org.eclipse.equinox.internal.provisional.p2.directorywatcher;

import org.eclipse.equinox.internal.provisional.p2.repository.IRepository;

import java.io.File;
import java.net.URI;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.update.Site;
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.metadata.IArtifactKey;
import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
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.*;
import org.eclipse.equinox.p2.publisher.*;
import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction;
import org.eclipse.equinox.p2.publisher.eclipse.FeaturesAction;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.util.NLS;

public class RepositoryListener extends DirectoryChangeListener {
	public static final String ARTIFACT_FOLDER = "artifact.folder"; //$NON-NLS-1$
	public static final String ARTIFACT_REFERENCE = "artifact.reference"; //$NON-NLS-1$
	public static final String FILE_LAST_MODIFIED = "file.lastModified"; //$NON-NLS-1$
	public static final String FILE_NAME = "file.name"; //$NON-NLS-1$
	private final IMetadataRepository metadataRepository;
	private final CachingArtifactRepository artifactRepository;
	// at any point in time currentFiles is the list of files/dirs that the watcher has seen and 
	// believes to be on disk.
	private final Map currentFiles = new HashMap();
	private final Collection polledSeenFiles = new HashSet();

	private EntryAdvice advice = new EntryAdvice();
	private PublisherInfo info;
	private IPublisherResult iusToAdd;
	private IPublisherResult iusToChange;

	/**
	 * Create a repository listener that watches the specified folder and generates repositories
	 * for its content.
	 * @param repositoryName the repository name to use for the repository
	 * @param hidden <code>true</code> if the repository should be hidden, <code>false</code> if not.
	 */
	public RepositoryListener(String repositoryName, boolean hidden) {
		URI location = Activator.getDefaultRepositoryLocation(this, repositoryName);
		metadataRepository = initializeMetadataRepository(repositoryName, location, hidden);
		artifactRepository = initializeArtifactRepository(repositoryName, location, hidden);
		initializePublisher();
	}

	public RepositoryListener(IMetadataRepository metadataRepository, IArtifactRepository artifactRepository) {
		this.artifactRepository = new CachingArtifactRepository(artifactRepository);
		this.metadataRepository = metadataRepository;
		initializePublisher();
	}

	private void initializePublisher() {
		info = new PublisherInfo();
		info.setArtifactRepository(artifactRepository);
		info.setMetadataRepository(metadataRepository);
		info.addAdvice(advice);
		info.setArtifactOptions(IPublisherInfo.A_INDEX);
	}

	protected CachingArtifactRepository initializeArtifactRepository(String repositoryName, URI repositoryLocation, boolean hidden) {
		IArtifactRepositoryManager manager = Activator.getArtifactRepositoryManager();
		if (manager == null)
			throw new IllegalStateException(Messages.artifact_repo_manager_not_registered);

		try {
			IArtifactRepository result = manager.loadRepository(repositoryLocation, null);
			return result == null ? null : new CachingArtifactRepository(result);
		} 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$
			}
			IArtifactRepository result = manager.createRepository(repositoryLocation, name, IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
			return result == null ? null : new CachingArtifactRepository(result);
		} catch (ProvisionException e) {
			LogHelper.log(e);
			throw new IllegalStateException(NLS.bind(Messages.failed_create_artifact_repo, repositoryLocation));
		}
	}

	protected IMetadataRepository initializeMetadataRepository(String repositoryName, URI repositoryLocation, boolean hidden) {
		IMetadataRepositoryManager manager = Activator.getMetadataRepositoryManager();
		if (manager == null)
			throw new IllegalStateException(Messages.metadata_repo_manager_not_registered);

		try {
			return manager.loadRepository(repositoryLocation, null);
		} catch (ProvisionException e) {
			//fall through and create new repository
		}
		try {
			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(repositoryLocation, name, IMetadataRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
		} catch (ProvisionException e) {
			LogHelper.log(e);
			throw new IllegalStateException(NLS.bind(Messages.failed_create_metadata_repo, repositoryLocation));
		}
	}

	public boolean added(File file) {
		return process(file, true);
	}

	public boolean changed(File file) {
		return process(file, false);
	}

	public boolean removed(File file) {
		// the IUs and artifacts associated with this file will get removed in stopPoll
		return currentFiles.containsKey(file);
	}

	private boolean process(File file, boolean isAddition) {
		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, isAddition);
		// could it be a bundle ?
		if (isDirectory || file.getName().endsWith(".jar")) //$NON-NLS-1$
			return processBundle(file, isDirectory, isAddition);
		return false;
	}

	private boolean processBundle(File file, boolean isDirectory, boolean isAddition) {
		BundleDescription bundleDescription = BundlesAction.createBundleDescription(file);
		if (bundleDescription == null)
			return false;

		advice.setProperties(file, file.lastModified(), file.toURI());
		return publish(new BundlesAction(new BundleDescription[] {bundleDescription}), isAddition);
		// TODO see bug 222370
		// we only want to return the bundle IU so must exclude all fragment IUs
		// not sure if this is still relevant but we should investigate.
	}

	private boolean processFeature(File file, boolean isAddition) {
		String link = (String) metadataRepository.getProperties().get(Site.PROP_LINK_FILE);
		advice.setProperties(file, file.lastModified(), file.toURI(), link);
		return publish(new FeaturesAction(new File[] {file}), isAddition);
	}

	private boolean publish(IPublisherAction action, boolean isAddition) {
		IPublisherResult result = isAddition ? iusToAdd : iusToChange;
		return action.perform(info, result, new NullProgressMonitor()).isOK();
	}

	public boolean isInterested(File file) {
		return true;
	}

	public Long getSeenFile(File file) {
		Long lastSeen = (Long) currentFiles.get(file);
		if (lastSeen != null)
			polledSeenFiles.add(file);
		return lastSeen;
	}

	public void startPoll() {
		iusToAdd = new PublisherResult();
		iusToChange = new PublisherResult();
		synchronizeCurrentFiles();
	}

	public void stopPoll() {
		final Set filesToRemove = new HashSet(currentFiles.keySet());
		filesToRemove.removeAll(polledSeenFiles);
		polledSeenFiles.clear();

		synchronizeMetadataRepository(filesToRemove);
		synchronizeArtifactRepository(filesToRemove);
		iusToAdd = null;
		iusToChange = null;
	}

	/**
	 * Flush all the pending changes to the metadata repository.
	 */
	private void synchronizeMetadataRepository(final Collection removedFiles) {
		if (metadataRepository == null)
			return;
		final Collection changes = iusToChange.getIUs(null, null);
		// first remove any IUs that have changed or that are associated with removed files
		if (!removedFiles.isEmpty() || !changes.isEmpty()) {
			// create a query that will identify all ius related to removed files or ius that have changed
			IMatchQuery removeQuery = new MatchQuery() {
				public boolean isMatch(Object candidate) {
					if (!(candidate instanceof IInstallableUnit))
						return false;
					IInstallableUnit iu = (IInstallableUnit) candidate;
					if (changes.contains(iu))
						return true;
					String filename = iu.getProperty(FILE_NAME);
					if (filename == null) {
						String message = NLS.bind(Messages.filename_missing, "installable unit", iu.getId()); //$NON-NLS-1$
						LogHelper.log(new Status(IStatus.ERROR, Activator.ID, message, null));
						return false;
					}
					File iuFile = new File(filename);
					return removedFiles.contains(iuFile);
				}
			};
			metadataRepository.removeInstallableUnits(removeQuery, null);
		}
		// Then add all the new IUs as well as the new copies of the ones that have changed
		Collection additions = iusToAdd.getIUs(null, null);
		additions.addAll(changes);
		if (!additions.isEmpty())
			metadataRepository.addInstallableUnits((IInstallableUnit[]) additions.toArray(new IInstallableUnit[additions.size()]));
	}

	/**
	 * Here the artifacts have all been added to the artifact repo.  Remove the
	 * descriptors related to any file that has been removed and flush the repo
	 * to ensure that all the additions and removals have been completed.
	 */
	private void synchronizeArtifactRepository(final Collection removedFiles) {
		if (artifactRepository == null)
			return;
		if (!removedFiles.isEmpty()) {
			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];
					String filename = descriptor.getRepositoryProperty(FILE_NAME);
					if (filename == null) {
						String message = NLS.bind(Messages.filename_missing, "artifact", descriptor.getArtifactKey()); //$NON-NLS-1$
						LogHelper.log(new Status(IStatus.ERROR, Activator.ID, message, null));
					} else {
						File artifactFile = new File(filename);
						if (removedFiles.contains(artifactFile))
							artifactRepository.removeDescriptor(descriptor);
					}
				}
			}
		}
		artifactRepository.save();
	}

	/**
	 * Prime the list of current files that the listener knows about.  This traverses the 
	 * repos and looks for the related filename and modified timestamp information.
	 */
	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();
				String filename = iu.getProperty(FILE_NAME);
				if (filename == null) {
					String message = NLS.bind(Messages.filename_missing, "installable unit", iu.getId()); //$NON-NLS-1$
					LogHelper.log(new Status(IStatus.ERROR, Activator.ID, message, null));
				} else {
					File iuFile = new File(filename);
					Long iuLastModified = new Long(iu.getProperty(FILE_LAST_MODIFIED));
					currentFiles.put(iuFile, iuLastModified);
				}
			}
		}
		//
		//		// TODO  should we be doing this for the artifact repo?  the metadata repo should
		//		// be the main driver here.
		//		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;
	}
}
