/*******************************************************************************
 * Copyright (c) 2000, 2007 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Atsuhiko Yamanaka, JCraft,Inc. - implementation of promptForKeyboradInteractive
 *******************************************************************************/
package org.eclipse.team.internal.ccvs.ui;

import java.util.Map;

import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.team.core.*;
import org.eclipse.team.internal.ccvs.core.*;

/**
 * An authenticator that prompts the user for authentication info,
 * and stores the results in the Platform's authentication key-ring.
 */
public class WorkbenchUserAuthenticator implements IUserAuthenticator {
	public static boolean USE_ALTERNATE_PROMPTER = false;
	
	/**
	 * WorkbenchUserAuthenticator constructor.
	 */
	public WorkbenchUserAuthenticator() {
		super();
		// Initialize USE_ALTERNATE_PROMPTER
		IIgnoreInfo[] ignores = Team.getAllIgnores();
		boolean found = false;
		for (int i = 0; i < ignores.length; i++) {
			if (ignores[i].getPattern().equals("*.notes")) { //$NON-NLS-1$
				found = true;
			}
		}
		if (!found) return;
		IStringMapping[] mappings = Team.getFileContentManager().getExtensionMappings();
		for (int i = 0; i < mappings.length; i++) {
			if (mappings[i].getString().equals("notes")) { //$NON-NLS-1$
				USE_ALTERNATE_PROMPTER = true;
				return;
			}
		}
		USE_ALTERNATE_PROMPTER = false;
	}
	@Override
	public void promptForUserInfo(final ICVSRepositoryLocation location, final IUserInfo userinfo, final String message) throws CVSException {
		if (!userinfo.isUsernameMutable() && USE_ALTERNATE_PROMPTER) {
			alternatePromptForUserInfo(userinfo);
			return;
		}
		// ask the user for a password
		final String[] result = new String[2];
		Display display = Display.getCurrent();
		final boolean allowCaching[] = {false};
		if (display != null) {
			allowCaching[0] = promptForPassword(location, userinfo.getUsername(), message, userinfo.isUsernameMutable(), result);
		} else {
			// sync exec in default thread
			final CVSException[] exception = new CVSException[] { null };
			Display.getDefault().syncExec(() -> {
				try {
					allowCaching[0] = promptForPassword(location, userinfo.getUsername(), message,
							userinfo.isUsernameMutable(), result);
				} catch (CVSException e) {
					exception[0] = e;
				}
			});
			if (exception[0] != null) {
				throw exception[0];
			}
		}
			
		if (result[0] == null) {
			throw new OperationCanceledException(CVSUIMessages.WorkbenchUserAuthenticator_cancelled); 
		}
		
		if (userinfo.isUsernameMutable()) {
			userinfo.setUsername(result[0]);
		
		}
		userinfo.setPassword(result[1]);
		
		if(location != null) {
			if (userinfo.isUsernameMutable()) {
				location.setUsername(result[0]);
			}
			location.setPassword(result[1]);
			location.setAllowCaching(allowCaching[0]);
		}
	}
	
	/**
	 * Asks the user to enter a password. Places the
	 * results in the supplied string[].  result[0] must
	 * contain the username, result[1] must contain the password.
	 * If the user canceled, both values must be zero.
	 * 
	 * @param location  the location to obtain the password for
	 * @param username  the username
	 * @param message  a message to display to the user
	 * @param userMutable  whether the user can be changed in the dialog
	 * @param result  a String array of length two in which to put the result
	 * @throws CVSException 
	 */
	private boolean promptForPassword(final ICVSRepositoryLocation location, final String username, final String message, final boolean userMutable, final String[] result) throws CVSException {
		String domain = location == null ? null : location.getLocation(true);
		boolean cachingCheckbox=true;
		
		if(location != null && location.getMethod().getName().equals("pserverssh2")){  //$NON-NLS-1$
			/**
			 * If this method 'promptForPassword' is invoked for ssh2 connection,
			 * we want to disable the checkbox for password caching, because it will
			 * overwrite the password for pserver with the password for ssh2.
			 * 
			 * In pserverssh2 connection type, its location name will be like
			 *    pserverssh2:pserver_username@ssh2_username@ssh2_host@pserver_host
			 *    
			 * The problem is that there is not a method to know if we are invoked from ssh2 or pserver.
			 * The following code will guess that if 'username' is equals to 'ssh2_userver' we are from ssh2,
			 * but if 'pserver2_username' is equals to 'ssh2_username', this guess will not be correct.
			 */
			String host = location.getHost();              // ssh2_username@ssh2_host@pserver_host
			int index = host.indexOf("@"); //$NON-NLS-1$
			if (index != -1) {
				cachingCheckbox = false;
				if (index != 0) {
					if (!username.equals(host.substring(0, index))) {
						cachingCheckbox = true;
					}
				}
			}
		}
		
		UserValidationDialog dialog = new UserValidationDialog(null, domain, (username==null)?"":username, message, cachingCheckbox);//$NON-NLS-1$
		dialog.setUsernameMutable(userMutable);
		dialog.open();	
		result[0] = dialog.getUsername();
		result[1] = dialog.getPassword();
		return dialog.getAllowCaching();
	}

	/**
	 * Asks the user to enter values. 
	 * 
	 * @param location  the location to obtain the password for
	 * @param destication the location
	 * @param name the name
	 * @param instruction the instruction
	 * @param prompt the titles for text fields
	 * @param echo '*' should be used or not
	 * @param result the entered values, or null if user canceled.
	 */
	@Override
	public String[] promptForKeyboradInteractive(final ICVSRepositoryLocation location,
							 final String destination,
							 final String name,
							 final String instruction,
							 final String[] prompt,
							 final boolean[] echo) throws CVSException {
		final String[][] result = new String[1][];
		final boolean[] allowCaching=new boolean[1];
		Display display = Display.getCurrent();
		if (display != null) {
		result[0]=_promptForUserInteractive(location, destination, name, instruction, prompt, echo, allowCaching);
		} 
		else {
			// sync exec in default thread
			Display.getDefault().syncExec(() -> result[0] = _promptForUserInteractive(location, destination, name,
					instruction, prompt, echo, allowCaching));
		}
		if (result[0] != null && location != null && 
				KeyboardInteractiveDialog.isPasswordAuth(prompt)) {
			location.setPassword(result[0][0]);
			location.setAllowCaching(allowCaching[0]);
		}
		return result[0];
	}

	private String[] _promptForUserInteractive(final ICVSRepositoryLocation location, 
							 final String destination,
							 final String name,
							 final String instruction,
							 final String[] prompt,
							 final boolean[] echo,
							 final boolean[] allowCaching) {
	
		String domain = location == null ? null : location.getLocation(true);
		String userName = location == null ? null : location.getUsername();
		boolean cachingCheckbox=true;
		
		if (location != null
				&& location.getMethod().getName().equals("pserverssh2")) { //$NON-NLS-1$
			/**
			 * We want to disable the checkbox for password caching, because it will
			 * overwrite the password for pserver with the password for ssh2.
			 * 
			 * In pserverssh2 connection type, its location name will be like
			 *    pserverssh2:pserver_username@ssh2_username@ssh2_host@pserver_host
			 * 
			 * 'userName' is 'pserver_username', so we also have to change it to 'ssh2_username'.
			 */
			String host = location.getHost();         // ssh2_username@ssh2_host@pserver_host
			int index = host.indexOf("@"); //$NON-NLS-1$
			if (index != -1) {
				if (index != 0) {
					userName = host.substring(0, index);
				}
				cachingCheckbox = false;
			}
		}
		
		KeyboardInteractiveDialog dialog = new KeyboardInteractiveDialog(null, 
										 domain,
										 destination,
										 name,
										 userName, 
										 instruction,
										 prompt,
										 echo,
										 cachingCheckbox);
		dialog.open();
		String[] _result=dialog.getResult();
		if(_result!=null)
			allowCaching[0]=dialog.getAllowCaching();
		return _result;
	}
	
	/**
	 * Special alternate prompting. Returns the password. Username must be fixed.
	 */
	private String alternatePromptForPassword(final String username) {
		AlternateUserValidationDialog dialog = new AlternateUserValidationDialog(null, (username == null) ? "" : username); //$NON-NLS-1$
		dialog.setUsername(username);
		int result = dialog.open();
		if (result == Window.CANCEL) return null;
		return dialog.getPassword();
	}
	
	/**
	 * Special alternate prompting.
	 */
	public void alternatePromptForUserInfo(final IUserInfo userinfo) {
		// ask the user for a password
		final String[] result = new String[1];
		Display display = Display.getCurrent();
		if (display != null) {
			result[0] = alternatePromptForPassword(userinfo.getUsername());
		} else {
			// sync exec in default thread
			Display.getDefault().syncExec(() -> result[0] = alternatePromptForPassword(userinfo.getUsername()));
		}
			
		if (result[0] == null) {
			throw new OperationCanceledException(CVSUIMessages.WorkbenchUserAuthenticator_The_operation_was_canceled_by_the_user_1); 
		}
		
		userinfo.setPassword(result[0]);
	}

	@Override
	public int prompt(final ICVSRepositoryLocation location, final int promptType, final String title, final String message, final int[] promptResponses, final int defaultResponse) {
		final Display display = CVSUIPlugin.getStandardDisplay();
		final int[] retval = new int[1];
		final String[] buttons = new String[promptResponses.length];
		for (int i = 0; i < promptResponses.length; i++) {
			int prompt = promptResponses[i];
			switch(prompt) { 
				case IUserAuthenticator.OK_ID: buttons[i] = IDialogConstants.OK_LABEL; break;
				case IUserAuthenticator.CANCEL_ID: buttons[i] = IDialogConstants.CANCEL_LABEL; break;
				case IUserAuthenticator.NO_ID: buttons[i] = IDialogConstants.NO_LABEL; break;
				case IUserAuthenticator.YES_ID: buttons[i] = IDialogConstants.YES_LABEL; break;
			}
		}
		
		display.syncExec(() -> {
			final MessageDialog dialog = new MessageDialog(new Shell(display), title, null /* title image */,
					NLS.bind(CVSUIMessages.WorkbenchUserAuthenticator_0, message, location.getLocation(true)),
					promptType, buttons, 1);
			retval[0] = dialog.open();
		});
		return retval[0];
	}
	
	@Override
	public boolean promptForHostKeyChange(final ICVSRepositoryLocation location) {
		final boolean[] openConfirm = new boolean[] { false };
		final Display display = CVSUIPlugin.getStandardDisplay();
		display.syncExec(
				() -> openConfirm[0] = MessageDialog.openConfirm(null, CVSUIMessages.WorkbenchUserAuthenticator_1,
						NLS.bind(CVSUIMessages.WorkbenchUserAuthenticator_2, new String[] { location.getHost() })));
		if (!openConfirm[0]) {
			throw new OperationCanceledException();
		}
		return openConfirm[0];
	}
	
	@Override
	public Map promptToConfigureRepositoryLocations(final Map alternativeMap) {
		final Map[] result = new Map[1];
		Display display = Display.getCurrent();
		if (display != null) {
			result[0] = openAlternativeRepositoryDialog(alternativeMap);
		} else {
			// sync exec in default thread
			Display.getDefault().syncExec(() -> result[0] = openAlternativeRepositoryDialog(alternativeMap));
		}
		return result[0];
	}
	
	/**
	 * Opens the Alternative Repository Selection dialog.
	 * 
	 * @param alternativeMap
	 * @return a map with selected repositories to use or <code>null</code>
	 *         when canceled.
	 */
	private Map openAlternativeRepositoryDialog(Map alternativeMap) {
		ConfigureRepositoryLocationsDialog dialog = new ConfigureRepositoryLocationsDialog(
				null, alternativeMap);
		int result = dialog.open();
		return result == IDialogConstants.CANCEL_ID ? null : dialog
				.getSelected();
	}
}
