/*******************************************************************************
 *  Copyright (c) 2007, 2017 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.equinox.internal.p2.reconciler.dropins;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.Map.Entry;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.extensionlocation.*;
import org.eclipse.equinox.internal.p2.update.*;
import org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryChangeListener;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.osgi.util.NLS;

/**
 * This class watches a platform.xml file. Note that we don't really need to use the DirectoryChangeListener
 * framework since we are doing a single poll on startup, but we will leave the code here in case we
 * want to watch for changes during a session. Note that the code to actually synchronize the repositories
 * is on the Activator so we will need to call out to that if this behaviour is changed.
 * 
 * @since 1.0
 */
public class PlatformXmlListener extends DirectoryChangeListener {

	private static final String PLATFORM_XML = "platform.xml"; //$NON-NLS-1$
	private boolean changed = false;
	private File root;
	private long lastModified = -1l;
	private Set<IMetadataRepository> configRepositories;

	private String toString(Feature[] features, String[] list) {
		StringBuffer buffer = new StringBuffer();
		if (features != null) {
			for (int i = 0; i < features.length; i++) {
				String featureURL = features[i].getUrl();
				if (featureURL != null)
					buffer.append(featureURL).append(',');
				else {
					String id = features[i].getId();
					String version = features[i].getVersion();
					if (id != null && version != null)
						buffer.append("features/" + id + "_" + version + "/,"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$					
				}
			}
		}
		if (list != null) {
			for (int i = 0; i < list.length; i++)
				buffer.append(list[i]).append(',');
		}
		if (buffer.length() == 0)
			return ""; //$NON-NLS-1$

		return buffer.substring(0, buffer.length() - 1);
	}

	/*
	 * Construct a new listener based on the given platform.xml file.
	 */
	public PlatformXmlListener(File file) {
		super();
		if (!PLATFORM_XML.equals(file.getName()))
			throw new IllegalArgumentException();
		this.root = file;
	}

	@Override
	public boolean added(File file) {
		changed = changed || PLATFORM_XML.equals(file.getName());
		return false;
	}

	@Override
	public boolean changed(File file) {
		changed = changed || PLATFORM_XML.equals(file.getName());
		return false;
	}

	@Override
	public Long getSeenFile(File file) {
		return Long.valueOf(0);
	}

	@Override
	public boolean isInterested(File file) {
		return file.getName().equals(PLATFORM_XML) && lastModified != file.lastModified();
	}

	@Override
	public boolean removed(File file) {
		changed = changed || PLATFORM_XML.equals(file.getName());
		return false;
	}

	@Override
	public void startPoll() {
		changed = false;
	}

	@Override
	public void stopPoll() {
		if (changed) {
			lastModified = root.lastModified();
			try {
				Configuration configuration = Configuration.load(root, Activator.getOSGiInstallArea());
				synchronizeConfiguration(configuration);
			} catch (ProvisionException e) {
				LogHelper.log(new Status(IStatus.ERROR, Activator.ID, Messages.errorProcessingConfg, e));
			}
		}
		changed = false;
	}

	public Collection<IMetadataRepository> getMetadataRepositories() {
		if (configRepositories == null)
			return Collections.<IMetadataRepository> emptySet();
		return configRepositories;
	}

	/*
	 * Look through the given list of repositories and see if there is one
	 * currently associated with the given url string. Return null if one could not
	 * be found.
	 */
	private IMetadataRepository getMatchingRepo(Collection<IMetadataRepository> repositoryList, String urlString) {
		if (repositoryList == null)
			return null;
		IPath urlPath = new Path(urlString).makeAbsolute();
		for (IMetadataRepository repo : repositoryList) {
			File file = URIUtil.toFile(repo.getLocation());
			if (file == null)
				continue;
			Path repoPath = new Path(file.getAbsolutePath());
			if (repoPath.makeAbsolute().equals(urlPath))
				return repo;
			// normalize the URLs to be the same
			if (repo instanceof ExtensionLocationMetadataRepository) {
				try {
					File one = ExtensionLocationMetadataRepository.getBaseDirectory(repo.getLocation());
					File two = ExtensionLocationMetadataRepository.getBaseDirectory(new URI(urlString));
					if (one.equals(two))
						return repo;
				} catch (ProvisionException e) {
					// Skip the repo if it's not found. Log all other errors.
					if (e.getStatus().getCode() != ProvisionException.REPOSITORY_NOT_FOUND)
						LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Error occurred while comparing repository locations.", e)); //$NON-NLS-1$
				} catch (URISyntaxException e) {
					LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Error occurred while comparing repository locations.", e)); //$NON-NLS-1$
				}
			}
		}
		return null;
	}

	/*
	 * Ensure that we have a repository for each site in the given configuration.
	 */
	protected void synchronizeConfiguration(Configuration config) {
		List<Site> sites = config.getSites();
		Set<IMetadataRepository> newRepos = new LinkedHashSet<>();
		Set<Site> toBeRemoved = new HashSet<>();
		for (Site site : sites) {
			String siteURL = site.getUrl();
			IMetadataRepository match = getMatchingRepo(Activator.getRepositories(), siteURL);
			if (match == null) {
				try {
					String linkFile = site.getLinkFile();
					if (linkFile != null && linkFile.length() > 0) {
						File link = new File(linkFile);
						if (!link.exists()) {
							toBeRemoved.add(site);
							continue;
						}
					}
					if (!site.isEnabled()) {
						toBeRemoved.add(site);
						continue;
					}
					String eclipseExtensionURL = siteURL + Constants.EXTENSION_LOCATION;
					// use the URI constructor here and not URIUtil#fromString because 
					// our string is already encoded
					URI location = new URI(eclipseExtensionURL);
					Map<String, String> properties = new HashMap<>();
					properties.put(SiteListener.SITE_POLICY, site.getPolicy());

					// In a "USER-INCLUDE" we add the site's features to the list
					// this is done to support backwards compatibility where previously features were not really installed.
					// One can always directly add the features to this list. This might be useful for excluding a particular feature
					// in a "USER-EXCLUDE" site. 
					Feature[] listFeatures = site.getPolicy().equals(Site.POLICY_USER_INCLUDE) ? site.getFeatures() : null;

					properties.put(SiteListener.SITE_LIST, toString(listFeatures, site.getList()));

					// deal with the metadata repository
					IMetadataRepository metadataRepository = null;
					try {
						metadataRepository = Activator.createExtensionLocationMetadataRepository(location, "extension location metadata repository: " + location.toString(), properties); //$NON-NLS-1$
					} catch (ProvisionException ex) {
						try {
							metadataRepository = Activator.loadMetadataRepository(location, null);
						} catch (ProvisionException inner) {
							// handle the case where someone has removed the extension location from
							// disk. Note: we use the siteURL not the eclipseextensionURL
							// use the URI constructor here and not URIUtil#fromString because 
							// our string is already encoded
							URI fileURI = new URI(siteURL);
							File file = URIUtil.toFile(fileURI);
							if (file != null && !file.exists()) {
								toBeRemoved.add(site);
								continue;
							}
							throw inner;
						}
						// set the repository properties here in case they have changed since the last time we loaded
						for (Entry<String, String> entry : properties.entrySet()) {
							metadataRepository.setProperty(entry.getKey(), entry.getValue());
						}
					}
					newRepos.add(metadataRepository);

					// now the artifact repository
					try {
						Activator.createExtensionLocationArtifactRepository(location, "extension location artifact repository: " + location, properties); //$NON-NLS-1$
					} catch (ProvisionException ex) {
						IArtifactRepository artifactRepository = Activator.loadArtifactRepository(location, null);
						// set the repository properties here in case they have changed since the last time we loaded
						for (Iterator<String> inner = properties.keySet().iterator(); inner.hasNext();) {
							String key = inner.next();
							String value = properties.get(key);
							artifactRepository.setProperty(key, value);
						}
					}
				} catch (URISyntaxException e) {
					LogHelper.log(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.errorLoadingRepository, siteURL), e));
				} catch (ProvisionException e) {
					// Skip the repo if it's not found. Log all other errors.
					if (e.getStatus().getCode() != ProvisionException.REPOSITORY_NOT_FOUND)
						LogHelper.log(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.errorLoadingRepository, siteURL), e));
				}
			} else {
				newRepos.add(match);
			}
		}
		if (!toBeRemoved.isEmpty()) {
			for (Iterator<Site> iter = toBeRemoved.iterator(); iter.hasNext();)
				config.removeSite(iter.next());
			try {
				config.save(root, Activator.getOSGiInstallArea());
			} catch (ProvisionException e) {
				LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Error occurred while saving configuration at: " + root, e)); //$NON-NLS-1$
			}
		}
		configRepositories = newRepos;
	}
}
