/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.taverna.workbench.file.impl.actions;

import static java.awt.EventQueue.invokeLater;
import static javax.swing.JOptionPane.ERROR_MESSAGE;
import static javax.swing.JOptionPane.showMessageDialog;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import org.apache.taverna.workbench.helper.HelpEnabledDialog;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;

/**
 * Simple dialogue to handle username/password input for workflow URL requiring
 * http authentication.
 * 
 * @author Stuart Owen
 * @author Stian Soiland-Reyes
 * @author Alan R Williams
 */
@SuppressWarnings("serial")
public class PasswordInput extends HelpEnabledDialog {
	private static Logger logger = Logger.getLogger(PasswordInput.class);

	private String password = null;
	private String username = null;
	private URL url = null;
	private int tryCount = 0;
	private final static int MAX_TRIES = 3;

	private JButton cancelButton;
	private JLabel jLabel1;
	private JLabel jLabel2;
	private JLabel messageLabel;
	private JButton okButton;
	private JPasswordField passwordTextField;
	private JLabel urlLabel;
	private JTextField usernameTextField;

	public void setUrl(URL url) {
		this.url = url;
		urlLabel.setText(url.toExternalForm());
	}

	public String getPassword() {
		return password;
	}

	public String getUsername() {
		return username;
	}

	public PasswordInput(JFrame parent) {
		super(parent, "Authorization", true, null);
		initComponents();
	}

	/** Creates new form PasswordInput */
	public PasswordInput() {
		super((JFrame) null, "Authorization", true, null);
		initComponents();
	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	private void initComponents() {
		usernameTextField = new javax.swing.JTextField();
		cancelButton = new javax.swing.JButton();
		okButton = new javax.swing.JButton();
		passwordTextField = new javax.swing.JPasswordField();
		jLabel1 = new javax.swing.JLabel();
		jLabel2 = new javax.swing.JLabel();
		messageLabel = new javax.swing.JLabel();
		urlLabel = new javax.swing.JLabel();

		getContentPane().setLayout(null);

		setModal(true);
		// setResizable(false);
		getContentPane().add(usernameTextField);
		usernameTextField.setBounds(20, 80, 280, 22);

		cancelButton.setText("Cancel");
		cancelButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				cancelButtonActionPerformed(evt);
			}
		});

		getContentPane().add(cancelButton);
		cancelButton.setBounds(230, 160, 75, 29);

		okButton.setText("OK");
		okButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				okButtonActionPerformed(evt);
			}
		});

		getContentPane().add(okButton);
		okButton.setBounds(150, 160, 75, 29);

		getContentPane().add(passwordTextField);
		passwordTextField.setBounds(20, 130, 280, 22);

		jLabel1.setText("Username");
		getContentPane().add(jLabel1);
		jLabel1.setBounds(20, 60, 70, 16);

		jLabel2.setText("Password");
		getContentPane().add(jLabel2);
		jLabel2.setBounds(20, 110, 70, 16);

		messageLabel.setText("A username and password is required for:");
		getContentPane().add(messageLabel);
		messageLabel.setBounds(20, 10, 270, 20);

		urlLabel.setText("service");
		getContentPane().add(urlLabel);
		urlLabel.setBounds(20, 30, 270, 16);

		pack();
	}

	private void okButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
		String password = String.valueOf(passwordTextField.getPassword());
		String username = usernameTextField.getText();
		HttpURLConnection connection;
		try {
			connection = (HttpURLConnection) url.openConnection();
			String userPassword = username + ":" + password;
			/*
			 * Note: non-latin1 support for basic auth is fragile/unsupported
			 * and must be MIME-encoded (RFC2047) according to
			 * https://bugzilla.mozilla.org/show_bug.cgi?id=41489
			 */
			byte[] encoded = Base64.encodeBase64(userPassword
					.getBytes("latin1"));
			connection.setRequestProperty("Authorization", "Basic "
					+ new String(encoded, "ascii"));
			connection.setRequestProperty("Accept", "text/xml");
			int code = connection.getResponseCode();

			/*
			 * NB: myExperiment gives a 500 response for an invalid
			 * username/password
			 */
			if (code == 401 || code == 500) {
				tryCount++;
				showMessageDialog(this, "The username and password failed",
						"Invalid username or password", ERROR_MESSAGE);
				if (tryCount >= MAX_TRIES) { // close after 3 attempts.
					this.password = null;
					this.username = null;
					this.setVisible(false);
				}
			} else {
				this.username = username;
				this.password = password;
				this.setVisible(false);
			}
		} catch (IOException ex) {
			logger.error("Could not get password", ex);
		}
	}

	private void cancelButtonActionPerformed(ActionEvent evt) {
		this.password = null;
		this.username = null;
		this.setVisible(false);
	}

	/**
	 * @param args
	 *            the command line arguments
	 */
	public static void main(String args[]) {
		invokeLater(new Runnable() {
			@Override
			public void run() {
				new PasswordInput().setVisible(true);
			}
		});
	}
}
