import java.util.Random;

import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JApplet;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JSlider;
import javax.swing.JCheckBox;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * @author Jens Gram, mail@jensgram.dk
 */
public final class JgPwdApplet extends JApplet implements ActionListener {

	private static final long serialVersionUID = 1L;
	
	private JTextField pwdResult;
	private JSlider prefLengthSlider;
	private JCheckBox prefNumberCheckbox;
	private JCheckBox prefSpecialCharsCheckbox;
	private JLabel prefLengthLabel;
	private JCheckBox prefMixedCaseCheckbox;
	private JButton generateButton;
	
	private Random pwdGenRand;
	private String pwdGenNumbers;
	private String pwdGenAlphabet;
	private String pwdGenAlphabetUpperCase;
	private String pwdGenSpecialChars;

	public JgPwdApplet() {
		super();
		
		this.pwdGenRand = new Random();
		this.pwdGenNumbers = "0123456789";
		this.pwdGenAlphabet = "abcdefghijklmnopqrstuvwxyz";
		this.pwdGenAlphabetUpperCase = pwdGenAlphabet.toUpperCase();
		this.pwdGenSpecialChars = "-.,#$%&";
	}

	public void init() {
		this.setSize(320, 140);
		
		JPanel contentPane = new JPanel();
		contentPane.setLayout(new BorderLayout());
		contentPane.add(getLengthPanel(), java.awt.BorderLayout.NORTH);
		contentPane.add(getPrefPanel(), java.awt.BorderLayout.CENTER);
		contentPane.add(getStatPanel(), java.awt.BorderLayout.EAST);
		contentPane.add(getResultPanel(), java.awt.BorderLayout.SOUTH);

		this.setContentPane(contentPane);
		
		generatePassword();
	}

	private JPanel getLengthPanel() {
		JPanel prefLengthPanel = new JPanel();
	
		// Label, description
		prefLengthPanel.add(new JLabel("Length:"));
		
		// Slider
		prefLengthSlider = new JSlider();
		prefLengthSlider.setMinimum(4);
		prefLengthSlider.setMaximum(32);
		prefLengthSlider.setMajorTickSpacing(4);
		prefLengthSlider.setMinorTickSpacing(2);
		prefLengthSlider.setPaintTicks(true);
		prefLengthSlider.setPaintTrack(true);
		prefLengthSlider.setValue(4);
		prefLengthSlider.addChangeListener(new ChangeListener() {
	
			public void stateChanged(ChangeEvent e) {
				int val = prefLengthSlider.getValue();
				
				// Work-around to make every change, but only "real" changes, count.
				if (!prefLengthLabel.getText().equals("" + val)) {
					prefLengthLabel.setText("" + val);
					generatePassword();
				}
			}
			
		});
		prefLengthPanel.add(prefLengthSlider);
	
		// Label, length
		prefLengthLabel = new JLabel();
		prefLengthLabel.setText("4");
		prefLengthLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
		prefLengthLabel.setPreferredSize(new java.awt.Dimension(30,20));
		prefLengthPanel.add(prefLengthLabel);
	
		return prefLengthPanel;
	}

	private JPanel getPrefPanel() {
		JPanel prefPanel = new JPanel(new GridLayout(3, 1));
		prefPanel.add(getPrefMixedCaseCheckbox());
		prefPanel.add(getPrefNumberCheckbox());
		prefPanel.add(getPrefSpecialCharsCheckbox());
	
		return prefPanel;
	}

	private JCheckBox getPrefMixedCaseCheckbox() {
		prefMixedCaseCheckbox = new JCheckBox();
		prefMixedCaseCheckbox.setText("Use mixed case");
		prefMixedCaseCheckbox.setSelected(true);
		prefMixedCaseCheckbox.addActionListener(this);
	
		return prefMixedCaseCheckbox;
	}

	private JCheckBox getPrefNumberCheckbox() {
		prefNumberCheckbox = new JCheckBox();
		prefNumberCheckbox.setText("Use numbers");
		prefNumberCheckbox.setSelected(true);
		prefNumberCheckbox.addActionListener(this);
	
		return prefNumberCheckbox;
	}

	private JCheckBox getPrefSpecialCharsCheckbox() {
		prefSpecialCharsCheckbox = new JCheckBox();
		prefSpecialCharsCheckbox.setText("Use special characters (" + pwdGenSpecialChars + ")");
		prefSpecialCharsCheckbox.addActionListener(this);
	
		return prefSpecialCharsCheckbox;
	}

	private JPanel getStatPanel() {
		JPanel statPanel = new JPanel(new BorderLayout());
		
		generateButton = new JButton("Generate");
		generateButton.addActionListener(this);
		
		statPanel.add(generateButton, java.awt.BorderLayout.SOUTH);

		return statPanel;
	}

	private JTextField getResultPanel() {
		pwdResult = new JTextField();
		pwdResult.setEditable(false);
		pwdResult.setHorizontalAlignment(javax.swing.JTextField.CENTER);
		pwdResult.setForeground(new java.awt.Color(208,51,51));
		pwdResult.setFont(new java.awt.Font("Dialog", java.awt.Font.BOLD, 14));
		
		return pwdResult;
	}

	/**
	 * Generates a random password according to the entered preferences.
	 */
	private void generatePassword() {
		String pwd = "";
		String chars = pwdGenAlphabet;
		
		/* Populate chars */
		// Numbers
		if (prefNumberCheckbox.isSelected()) {
			chars += pwdGenNumbers;
		}
		
		// Special characters
		if (prefSpecialCharsCheckbox.isSelected()) {
			chars += pwdGenSpecialChars;
		}
		
		// Mixed
		if (prefMixedCaseCheckbox.isSelected()) {
			chars += pwdGenAlphabetUpperCase;
		}
		
		for (int i = 0; i < prefLengthSlider.getValue(); i++) {
			int rInt = pwdGenRand.nextInt(chars.length());
			
			pwd += chars.charAt(rInt);
		}
		
		pwdResult.setText(pwd);
	}

	public void actionPerformed(ActionEvent e) {
		generatePassword();
	}
}