/*
 * Copyright (C) 2010, Google Inc.
 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.eclipse.jgit.awtui;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import org.eclipse.jgit.errors.UnsupportedCredentialItem;
import org.eclipse.jgit.transport.CredentialItem;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.URIish;

/** Interacts with the user during authentication by using AWT/Swing dialogs. */
public class AwtCredentialsProvider extends CredentialsProvider {
	/** Install this implementation as the default. */
	public static void install() {
		CredentialsProvider.setDefault(new AwtCredentialsProvider());
	}

	@Override
	public boolean isInteractive() {
		return true;
	}

	@Override
	public boolean supports(CredentialItem... items) {
		for (CredentialItem i : items) {
			if (i instanceof CredentialItem.StringType)
				continue;

			else if (i instanceof CredentialItem.CharArrayType)
				continue;

			else if (i instanceof CredentialItem.YesNoType)
				continue;

			else if (i instanceof CredentialItem.InformationalMessage)
				continue;

			else
				return false;
		}
		return true;
	}

	@Override
	public boolean get(URIish uri, CredentialItem... items)
			throws UnsupportedCredentialItem {
		if (items.length == 0) {
			return true;

		} else if (items.length == 1) {
			final CredentialItem item = items[0];

			if (item instanceof CredentialItem.InformationalMessage) {
				JOptionPane.showMessageDialog(null, item.getPromptText(),
						UIText.get().warning, JOptionPane.INFORMATION_MESSAGE);
				return true;

			} else if (item instanceof CredentialItem.YesNoType) {
				CredentialItem.YesNoType v = (CredentialItem.YesNoType) item;
				int r = JOptionPane.showConfirmDialog(null, v.getPromptText(),
						UIText.get().warning, JOptionPane.YES_NO_OPTION);
				switch (r) {
				case JOptionPane.YES_OPTION:
					v.setValue(true);
					return true;

				case JOptionPane.NO_OPTION:
					v.setValue(false);
					return true;

				case JOptionPane.CANCEL_OPTION:
				case JOptionPane.CLOSED_OPTION:
				default:
					return false;
				}

			} else {
				return interactive(uri, items);
			}

		} else {
			return interactive(uri, items);
		}
	}

	private boolean interactive(URIish uri, CredentialItem[] items) {
		final GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 1, 1,
				GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
				new Insets(0, 0, 0, 0), 0, 0);
		final JPanel panel = new JPanel();
		panel.setLayout(new GridBagLayout());

		final JTextField[] texts = new JTextField[items.length];
		for (int i = 0; i < items.length; i++) {
			CredentialItem item = items[i];

			if (item instanceof CredentialItem.StringType
					|| item instanceof CredentialItem.CharArrayType) {
				gbc.fill = GridBagConstraints.NONE;
				gbc.gridwidth = GridBagConstraints.RELATIVE;
				gbc.gridx = 0;
				panel.add(new JLabel(item.getPromptText()), gbc);

				gbc.fill = GridBagConstraints.HORIZONTAL;
				gbc.gridwidth = GridBagConstraints.RELATIVE;
				gbc.gridx = 1;
				if (item.isValueSecure())
					texts[i] = new JPasswordField(20);
				else
					texts[i] = new JTextField(20);
				panel.add(texts[i], gbc);
				gbc.gridy++;

			} else if (item instanceof CredentialItem.InformationalMessage) {
				gbc.fill = GridBagConstraints.NONE;
				gbc.gridwidth = GridBagConstraints.REMAINDER;
				gbc.gridx = 0;
				panel.add(new JLabel(item.getPromptText()), gbc);
				gbc.gridy++;

			} else {
				throw new UnsupportedCredentialItem(uri, item.getPromptText());
			}
		}

		if (JOptionPane.showConfirmDialog(null, panel,
				UIText.get().authenticationRequired,
				JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) != JOptionPane.OK_OPTION)
			return false; // cancel

		for (int i = 0; i < items.length; i++) {
			CredentialItem item = items[i];
			JTextField f = texts[i];

			if (item instanceof CredentialItem.StringType) {
				CredentialItem.StringType v = (CredentialItem.StringType) item;
				if (f instanceof JPasswordField)
					v.setValue(new String(((JPasswordField) f).getPassword()));
				else
					v.setValue(f.getText());

			} else if (item instanceof CredentialItem.CharArrayType) {
				CredentialItem.CharArrayType v = (CredentialItem.CharArrayType) item;
				if (f instanceof JPasswordField)
					v.setValueNoCopy(((JPasswordField) f).getPassword());
				else
					v.setValueNoCopy(f.getText().toCharArray());
			}
		}
		return true;
	}
}
