/*******************************************************************************
 * Copyright (c) 2009, 2015 IBM Corporation and others.
 * The code, documentation and other materials contained herein have been
 * licensed under the Eclipse Public License - v 1.0 by the copyright holder
 * listed above, as the Initial Contributor under such license. The text of
 * such license is available at www.eclipse.org.
 * Contributors:
 * 	IBM Corporation - Initial API and implementation
 *  Cloudsmith Inc - Implementation
 *  Sonatype Inc - Ongoing development
 *  Red Hat Inc. - Bug 460967
 ******************************************************************************/

package org.eclipse.equinox.internal.p2.repository;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
import org.eclipse.equinox.internal.p2.repository.helpers.DebugHelper;
import org.eclipse.equinox.p2.core.*;
import org.eclipse.equinox.p2.repository.IRepository;
import org.eclipse.equinox.security.storage.*;

/**
 * Credentials handles AuthenticationInfo that can be used to established an
 * ECF connection context. An AuthenticationInfo is obtained for a URI buy looking
 * in a store, if none is provided the user is optionally prompted for the information. 
 */
public class Credentials {
	public static class LoginCanceledException extends Exception {
		private static final long serialVersionUID = 1L;

	}

	/** 
	 * Cache of auth information that is not persisted, and modified auth info.
	 */
	private static final Map<String, UIServices.AuthenticationInfo> savedAuthInfo = Collections.synchronizedMap(new HashMap<String, UIServices.AuthenticationInfo>());

	/**
	 * Information about retry counts, and prompts canceled by user. The SoftReference is
	 * a Map if not null. The keys are also used as serialization per host.
	 */
	private static Map<String, HostEntry> remembered;

	/** 
	 * Serializes pop up of login/password prompt 
	 */
	private static final Object promptLock = new Object();

	/**
	 * Returns the AuthenticationInfo for the given URI. This may prompt the
	 * user for user name and password as required.
	 * 
	 * If the URI is opaque, the entire URI is used as the key. For non opaque URIs, 
	 * the key is based on the host name, using a host name of "localhost" if host name is
	 * missing.
	 *
	 * @param location - the file location requiring login details
	 * @param prompt - use <code>true</code> to prompt the user instead of
	 * looking at the secure preference store for login, use <code>false</code>
	 * to only try the secure preference store
	 * @throws LoginCanceledException when the user cancels the login prompt
	 * @throws CoreException if the password cannot be read or saved
	 * @return The authentication info.
	 */
	public static UIServices.AuthenticationInfo forLocation(URI location, boolean prompt) throws LoginCanceledException, CoreException {
		return forLocation(location, prompt, null);
	}

	/**
	 * Returns the AuthenticationInfo for the given URI. This may prompt the
	 * user for user name and password as required.
	 * 
	 * If the URI is opaque, the entire URI is used as the key. For non opaque URIs, 
	 * the key is based on the host name, using a host name of "localhost" if host name is
	 * missing.
	 * 
	 * This method allows passing a previously used AuthenticationInfo. If set, the user interface
	 * may present the information "on file" to the user for editing.
	 * 
	 * @param location - the location for which to obtain authentication information
	 * @param prompt - if true, user will be prompted for information
	 * @param lastUsed - optional information used in an previous attempt to login
	 * @return AuthenticationInfo, or null if there was no information available
	 * @throws LoginCanceledException - user canceled the prompt for name/password
	 * @throws CoreException if there is an error
	 */
	public static UIServices.AuthenticationInfo forLocation(URI location, boolean prompt, UIServices.AuthenticationInfo lastUsed) throws LoginCanceledException, CoreException {
		String host = uriToHost(location);
		String nodeKey;
		try {
			nodeKey = URLEncoder.encode(host, "UTF-8"); //$NON-NLS-1$
		} catch (UnsupportedEncodingException e2) {
			// fall back to default platform encoding
			try {
				// Uses getProperty "file.encoding" instead of using deprecated URLEncoder.encode(String location) 
				// which does the same, but throws NPE on missing property.
				String enc = System.getProperty("file.encoding");//$NON-NLS-1$
				if (enc == null)
					throw new UnsupportedEncodingException("No UTF-8 encoding and missing system property: file.encoding"); //$NON-NLS-1$
				nodeKey = URLEncoder.encode(host, enc);
			} catch (UnsupportedEncodingException e) {
				throw internalError(e);
			}
		}
		if (DebugHelper.DEBUG_REPOSITORY_CREDENTIALS) {
			DebugHelper.debug("Credentials", "forLocation:ENTER", // //$NON-NLS-1$ //$NON-NLS-2$
					new Object[] {"host", location, "prompt", Boolean.toString(prompt)}); //$NON-NLS-1$ //$NON-NLS-2$
		}

		// Must serialize getting stored permissions per host as the location may
		// be prompted right now
		// Start by getting a key to lock on
		HostEntry hostLock = null;
		synchronized (Credentials.class) {
			Map<String, HostEntry> r = getRemembered();
			hostLock = r.get(host);
			if (hostLock == null) {
				hostLock = new HostEntry(0);
				r.put(host, hostLock);
			}
		}
		UIServices.AuthenticationInfo loginDetails = null;
		ISecurePreferences securePreferences = null;
		// synchronize getting secure store with prompting user, as it may prompt.
		synchronized (promptLock) {
			securePreferences = SecurePreferencesFactory.getDefault();
		}

		// serialize the prompting per host
		synchronized (hostLock) {
			try {
				if (DebugHelper.DEBUG_REPOSITORY_CREDENTIALS) {
					DebugHelper.debug("Credentials", "forLocation:HOSTLOCK OBTAINED", // //$NON-NLS-1$ //$NON-NLS-2$
							new Object[] {"host", location, "prompt", Boolean.toString(prompt)}); //$NON-NLS-1$ //$NON-NLS-2$
				}

				String nodeName = IRepository.PREFERENCE_NODE + '/' + nodeKey;
				ISecurePreferences prefNode = null;
				try {
					if (securePreferences.nodeExists(nodeName))
						prefNode = securePreferences.node(nodeName);
				} catch (IllegalArgumentException e) {
					// if the node name is illegal/malformed (should not happen).
					throw internalError(e);
				} catch (IllegalStateException e) {
					// thrown if preference store has been tampered with
					throw internalError(e);
				}
				if (!prompt) {
					try {
						if (prefNode != null) {
							String username = prefNode.get(IRepository.PROP_USERNAME, null);
							String password = prefNode.get(IRepository.PROP_PASSWORD, null);
							if (DebugHelper.DEBUG_REPOSITORY_CREDENTIALS) {
								if (username != null && password != null) {
									DebugHelper.debug("Credentials", "forLocation:PREFNODE FOUND - USING STORED INFO", // //$NON-NLS-1$ //$NON-NLS-2$
											new Object[] {"host", location, "prompt", Boolean.toString(prompt)}); //$NON-NLS-1$ //$NON-NLS-2$
								}
							}

							// if we don't have stored connection data just return a null auth info
							if (username != null && password != null)
								return new UIServices.AuthenticationInfo(username, password, true);
						}
						if (DebugHelper.DEBUG_REPOSITORY_CREDENTIALS) {
							DebugHelper.debug("Credentials", "forLocation:PREFNODE NOT FOUND - RETURN FROM MEMORY", // //$NON-NLS-1$ //$NON-NLS-2$
									new Object[] {"host", location, "prompt", Boolean.toString(prompt)}); //$NON-NLS-1$ //$NON-NLS-2$
						}
						return restoreFromMemory(nodeName);
					} catch (StorageException e) {
						throw internalError(e);
					}
				}
				// need to prompt user for user name and password
				// first check (throw exception) if having a remembered cancel
				checkRememberedCancel(host);

				// check if another thread has modified the credentials since last attempt
				// made by current thread - if so, try with latest without prompting
				if (DebugHelper.DEBUG_REPOSITORY_CREDENTIALS) {
					UIServices.AuthenticationInfo latest = restoreFromMemory(nodeName);
					boolean useLatest = false;
					if (latest != null && lastUsed != null)
						if (!(latest.getUserName().equals(lastUsed.getUserName()) && latest.getPassword().equals(lastUsed.getPassword())))
							useLatest = true;
					if (useLatest)
						DebugHelper.debug("Credentials", "forLocation:LATER INFO AVAILABLE - RETURNING IT", // //$NON-NLS-1$ //$NON-NLS-2$
								new Object[] {"host", location, "prompt", Boolean.toString(prompt)}); //$NON-NLS-1$ //$NON-NLS-2$
				}

				UIServices.AuthenticationInfo latest = restoreFromMemory(nodeName);
				if (latest != null)
					if (lastUsed == null || !(latest.getUserName().equals(lastUsed.getUserName()) && latest.getPassword().equals(lastUsed.getPassword())))
						return latest;

				// check if number of prompts have been exceeded for the host - if so
				// do a synthetic Login canceled by user
				// (The alternative is to return "latest" until retry login gives up with
				// authentication failed - but that would waste time).
				if (DebugHelper.DEBUG_REPOSITORY_CREDENTIALS) {
					if (getPromptCount(host) >= RepositoryPreferences.getLoginRetryCount()) {
						if (lastUsed == null && latest == null)
							DebugHelper.debug("Credentials", "forLocation:NO INFO - SYNTHETIC CANCEL", // //$NON-NLS-1$ //$NON-NLS-2$
									new Object[] {"host", location}); //$NON-NLS-1$ 
						return latest == null ? lastUsed : latest; // keep client failing on the latest known
					}
					DebugHelper.debug("Credentials", "forLocation:LATER INFO AVAILABLE - RETURNING IT", // //$NON-NLS-1$ //$NON-NLS-2$
							new Object[] {"host", location, "prompt", Boolean.toString(prompt)}); //$NON-NLS-1$ //$NON-NLS-2$

				}
				if (getPromptCount(host) >= RepositoryPreferences.getLoginRetryCount()) {
					if (lastUsed == null && latest == null)
						throw new LoginCanceledException();
					return latest == null ? lastUsed : latest; // keep client failing on the latest known
				}
				IProvisioningAgent agent = ServiceHelper.getService(Activator.getContext(), IProvisioningAgent.class);
				UIServices adminUIService = (UIServices) agent.getService(UIServices.SERVICE_NAME);

				if (adminUIService != null)
					synchronized (promptLock) {
						try {
							if (DebugHelper.DEBUG_REPOSITORY_CREDENTIALS) {
								DebugHelper.debug("Credentials", "forLocation:PROMPTLOCK OBTAINED", // //$NON-NLS-1$ //$NON-NLS-2$
										new Object[] {"host", location}); //$NON-NLS-1$ 					
							}

							// serialize the popping of the dialog itself
							loginDetails = lastUsed != null ? adminUIService.getUsernamePassword(host, lastUsed) : adminUIService.getUsernamePassword(host);
							//null result means user canceled password dialog
							if (DebugHelper.DEBUG_REPOSITORY_CREDENTIALS) {
								if (loginDetails == UIServices.AUTHENTICATION_PROMPT_CANCELED)
									DebugHelper.debug("Credentials", "forLocation:PROMPTED - USER CANCELED (PROMPT LOCK RELEASED)", // //$NON-NLS-1$ //$NON-NLS-2$
											new Object[] {"host", location}); //$NON-NLS-1$					
							}
							if (loginDetails == UIServices.AUTHENTICATION_PROMPT_CANCELED) {
								rememberCancel(host);
								throw new LoginCanceledException();
							} else if (loginDetails == null) {
								throw new LoginCanceledException();
							}
							//save user name and password if requested by user
							if (DebugHelper.DEBUG_REPOSITORY_CREDENTIALS) {
								if (loginDetails.saveResult())
									DebugHelper.debug("Credentials", "forLocation:SAVING RESULT", // //$NON-NLS-1$ //$NON-NLS-2$
											new Object[] {"host", location}); //$NON-NLS-1$					
							}

							if (loginDetails.saveResult()) {
								if (prefNode == null)
									prefNode = securePreferences.node(nodeName);
								try {
									prefNode.put(IRepository.PROP_USERNAME, loginDetails.getUserName(), true);
									prefNode.put(IRepository.PROP_PASSWORD, loginDetails.getPassword(), true);
									prefNode.flush();
								} catch (StorageException e1) {
									throw internalError(e1);
								} catch (IOException e) {
									throw internalError(e);
								}
							} else {
								// if persisted earlier - the preference should be removed
								if (securePreferences.nodeExists(nodeName)) {
									if (DebugHelper.DEBUG_REPOSITORY_CREDENTIALS) {
										DebugHelper.debug("Credentials", "forLocation:REMOVING PREVIOUSLY SAVED INFO", // //$NON-NLS-1$ //$NON-NLS-2$
												new Object[] {"host", location}); //$NON-NLS-1$					
									}

									prefNode = securePreferences.node(nodeName);
									prefNode.removeNode();
									try {
										prefNode.flush();
									} catch (IOException e) {
										throw internalError(e);
									}
								}
							}
							saveInMemory(nodeName, loginDetails);
						} finally {
							if (DebugHelper.DEBUG_REPOSITORY_CREDENTIALS) {
								DebugHelper.debug("Credentials", "forLocation:PROMPTLOCK RELEASED", // //$NON-NLS-1$ //$NON-NLS-2$
										new Object[] {"host", location}); //$NON-NLS-1$					
							}
						}
					}
				incrementPromptCount(host);
			} finally {
				if (DebugHelper.DEBUG_REPOSITORY_CREDENTIALS) {
					DebugHelper.debug("Credentials", "forLocation:HOSTLOCK RELEASED", // //$NON-NLS-1$ //$NON-NLS-2$
							new Object[] {"host", location}); //$NON-NLS-1$					
				}
			}

		}

		return loginDetails;
	}

	private static String uriToHost(URI location) {
		// if URI is not opaque, just getting the host may be enough
		String host = location.getHost();
		if (host == null) {
			String scheme = location.getScheme();
			if (URIUtil.isFileURI(location) || scheme == null)
				// If the URI references a file, a password could possibly be needed for the directory
				// (it could be a protected zip file representing a compressed directory) - in this
				// case the key is the path without the last segment.
				// Using "Path" this way may result in an empty string - which later will result in
				// an invalid key.
				host = new Path(location.toString()).removeLastSegments(1).toString();
			else
				// it is an opaque URI - details are unknown - can only use entire string.
				host = location.toString();
		}
		return host;
	}

	/**
	 * Returns authentication details stored in memory for the given node name,
	 * or <code>null</code> if no information is stored.
	 */
	private static UIServices.AuthenticationInfo restoreFromMemory(String nodeName) {
		return savedAuthInfo.get(nodeName);
	}

	/**
	 * Saves authentication details in memory so user is only prompted once per (SDK) session
	 */
	private static void saveInMemory(String nodeName, UIServices.AuthenticationInfo loginDetails) {
		savedAuthInfo.put(nodeName, loginDetails);
	}

	/**
	 * Remember the fact that the host was canceled.
	 * @param host
	 */
	private static void rememberCancel(String host) {
		Map<String, HostEntry> r = getRemembered();
		if (r != null)
			r.put(host, new HostEntry(-1));
	}

	/**
	 * Throws LoginCancledException if the host was previously canceled, and the information
	 * is not stale.
	 * @param host
	 * @throws LoginCanceledException
	 */
	private static void checkRememberedCancel(String host) throws LoginCanceledException {
		Map<String, HostEntry> r = getRemembered();
		if (r != null) {
			Object x = r.get(host);
			if (x != null && x instanceof HostEntry)
				if (((HostEntry) x).isCanceled()) {
					if (DebugHelper.DEBUG_REPOSITORY_CREDENTIALS) {
						DebugHelper.debug("Credentials", "checkRememberCancel:PREVIOUSLY CANCELED", // //$NON-NLS-1$ //$NON-NLS-2$
								new Object[] {"host", host}); //$NON-NLS-1$ 
					}

					throw new LoginCanceledException();
				}
		}

	}

	/**
	 * Increments the prompt count for host. If information is stale, the count is restarted
	 * at 1.
	 * @param host
	 */
	private static void incrementPromptCount(String host) {
		Map<String, HostEntry> r = getRemembered();
		if (r != null) {
			HostEntry value = r.get(host);
			if (value == null)
				r.put(host, value = new HostEntry(1));
			else {
				if (value.isStale())
					value.reset();
				value.increment();
			}
		}
	}

	/**
	 * Returns prompt count for host, except if information is stale in which case 0 is returned.
	 * @param host
	 * @return number of time prompt has been performed for a host (or 0 if information is stale)
	 */
	private static int getPromptCount(String host) {
		Map<String, HostEntry> r = getRemembered();
		if (r != null) {
			HostEntry value = r.get(host);
			if (value != null && !value.isStale())
				return value.getCount();
		}
		return 0;

	}

	/**
	 * Clears the cached information about prompts for all login/password and
	 * canceled logins.
	 */
	public static synchronized void clearPromptCache() {
		if (remembered == null)
			return;
		Map<String, HostEntry> r = remembered;
		if (r == null || r.isEmpty())
			return;
		// reset entries rather than creating a new empty map since the entries
		// are also used as locks
		for (HostEntry entry : r.values())
			entry.reset();
	}

	/**
	 * Clears the cached information for location about prompts for login/password and
	 * canceled logins.
	 * @param location the repository location
	 */
	public static synchronized void clearPromptCache(URI location) {
		clearPromptCache(uriToHost(location));
	}

	/**
	 * Clears the cached information for host about prompts for login/password and
	 * canceled logins. 
	 * @param host a host as returned from uriToHost for a location
	 */
	public static synchronized void clearPromptCache(String host) {
		if (remembered == null)
			return;
		Map<String, HostEntry> r = remembered;
		if (r == null)
			return;
		HostEntry value = r.get(host);
		if (value != null)
			value.reset();
	}

	private static synchronized Map<String, HostEntry> getRemembered() {
		if (remembered == null)
			remembered = Collections.synchronizedMap(new HashMap<String, HostEntry>());
		return remembered;
	}

	private static class HostEntry {
		long timestamp;
		int count;

		public HostEntry(int count) {
			this.count = count;
			this.timestamp = System.currentTimeMillis();
		}

		public boolean isCanceled() {
			return count == -1 && !isStale();
		}

		public boolean isStale() {
			// a record is stale if older than 3 minutes
			return System.currentTimeMillis() - timestamp > 1000 * 60 * 3;
		}

		public int getCount() {
			return count;
		}

		public void increment() {
			if (count != -1)
				count++;
		}

		public void reset() {
			count = 0;
			timestamp = System.currentTimeMillis();
		}
	}

	/**
	 * Get default "InternalError" ProvisionException.
	 * @param t
	 * @return a default "InternalError"
	 */
	public static ProvisionException internalError(Throwable t) {
		return new ProvisionException(new Status(IStatus.ERROR, Activator.ID, //
				ProvisionException.INTERNAL_ERROR, Messages.repoMan_internalError, t));
	}
}
