/* File: EditUserPane.java
 * Author: Jason Gookins
 * Description: Allows an admin to edit an existing user.
 */

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Insets;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class EditUserPane extends JPanel implements ActionListener, ListSelectionListener
{
	/************************
	 ** Instance Variables **
	 ************************/

	private Belief belief;
	private DefaultListModel userList;
	private JList userListDisplay;
	private JCheckBox usernameCheckBox, passwordCheckBox;
	private JLabel newUsernameLabel, newPasswordLabel, confirmLabel;
	private JTextField usernameTextField;
	private JPasswordField passwordField, confirmField;
	private JButton okayButton, cancelButton;



	/**********************
	 ** Main Constructor **
	 **********************/

	public EditUserPane(Belief belief)
	{
		this.belief = belief;

		setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();

		JLabel editUserLabel = new JLabel("Edit User", JLabel.CENTER);
		editUserLabel.setFont(new Font("SansSerif", Font.PLAIN, 20));
		editUserLabel.setPreferredSize(new Dimension(200, 60));
		c.gridx = 0;
		c.gridy = 0;
		c.gridwidth = 2;
		c.gridheight = 1;
		c.fill = GridBagConstraints.BOTH;
		add(editUserLabel, c);

		JPanel usersPanel = new JPanel(new GridBagLayout());
		TitledBorder titledBorder = BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLACK), "Users");
		titledBorder.setTitleJustification(TitledBorder.CENTER);
		usersPanel.setBorder(titledBorder);
		usersPanel.setPreferredSize(new Dimension(360, 125));
		usersPanel.setMinimumSize(new Dimension(360, 125));
		GridBagConstraints d = new GridBagConstraints();

		JPanel userListPanel = new JPanel(new GridBagLayout());
		GridBagConstraints e = new GridBagConstraints();

		userList = new DefaultListModel();
		userListDisplay = new JList(userList);
		userListDisplay.setLayoutOrientation(JList.HORIZONTAL_WRAP);
		userListDisplay.setPrototypeCellValue("12345678901");
		userListDisplay.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		userListDisplay.setVisibleRowCount(-1);
		userListDisplay.addListSelectionListener(this);
		e.weightx = 1.0;
		e.weighty = 1.0;
		e.fill = GridBagConstraints.BOTH;
		userListPanel.add(userListDisplay, e);

		JScrollPane userListScrollPane = new JScrollPane(userListPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		d.weightx = 1.0;
		d.weighty = 1.0;
		d.insets = new Insets(5, 5, 5, 5);
		d.fill = GridBagConstraints.BOTH;
		usersPanel.add(userListScrollPane, d);

		c.gridy = 1;
		c.fill = GridBagConstraints.NONE;
		add(usersPanel, c);

		JPanel inputPanel = new JPanel(new GridBagLayout());
		titledBorder = BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLACK), "User Data");
		titledBorder.setTitleJustification(TitledBorder.CENTER);
		inputPanel.setBorder(titledBorder);
		inputPanel.setPreferredSize(new Dimension(360, 175));
		inputPanel.setMinimumSize(new Dimension(360, 175));
		GridBagConstraints f = new GridBagConstraints();

		usernameCheckBox = new JCheckBox("Change Username");
		usernameCheckBox.setEnabled(false);
		usernameCheckBox.addActionListener(this);
		f.gridx = 0;
		f.gridy = 0;
		f.gridwidth = 2;
		f.gridheight = 1;
		f.insets = new Insets(0, 0, 5, 0);
		f.fill = GridBagConstraints.NONE;
		inputPanel.add(usernameCheckBox, f);

		newUsernameLabel = new JLabel("New Username:");
		newUsernameLabel.setEnabled(false);
		f.gridy = 1;
		f.gridwidth = 1;
		f.insets = new Insets(5, 0, 5, 5);
		inputPanel.add(newUsernameLabel, f);

		passwordCheckBox = new JCheckBox("Change Password");
		passwordCheckBox.setEnabled(false);
		passwordCheckBox.addActionListener(this);
		f.gridy = 2;
		f.gridwidth = 2;
		f.insets = new Insets(5, 0, 5, 0);
		inputPanel.add(passwordCheckBox, f);

		newPasswordLabel = new JLabel("New Password:");
		newPasswordLabel.setEnabled(false);
		f.gridy = 3;
		f.gridwidth = 1;
		f.insets = new Insets(5, 0, 5, 5);
		inputPanel.add(newPasswordLabel, f);

		confirmLabel = new JLabel("Confirm Password:");
		confirmLabel.setEnabled(false);
		f.gridy = 4;
		f.insets = new Insets(5, 0, 5, 5);
		inputPanel.add(confirmLabel, f);

		usernameTextField = new JTextField();
		usernameTextField.setEnabled(false);
		usernameTextField.setPreferredSize(new Dimension(200, 20));
		usernameTextField.setMinimumSize(new Dimension(200, 20));
		usernameTextField.addActionListener(this);
		f.gridx = 1;
		f.gridy = 1;
		f.insets = new Insets(0, 10, 5, 5);
		f.fill = GridBagConstraints.BOTH;
		inputPanel.add(usernameTextField, f);

		passwordField = new JPasswordField();
		passwordField.setEnabled(false);
		passwordField.setPreferredSize(new Dimension(200, 20));
		passwordField.setMinimumSize(new Dimension(200, 20));
		passwordField.addActionListener(this);
		f.gridy = 3;
		f.insets = new Insets(5, 10, 5, 5);
		inputPanel.add(passwordField, f);

		confirmField = new JPasswordField();
		confirmField.setEnabled(false);
		confirmField.setPreferredSize(new Dimension(200, 20));
		confirmField.setMinimumSize(new Dimension(200, 20));
		confirmField.addActionListener(this);
		f.gridy = 4;
		f.insets = new Insets(5, 10, 5, 5);
		inputPanel.add(confirmField, f);		

		c.gridy = 2;
		add(inputPanel, c);

		okayButton = new JButton("Okay");
		okayButton.setEnabled(false);
		okayButton.setPreferredSize(new Dimension(75, 30));
		okayButton.setMinimumSize(new Dimension(75, 30));
		okayButton.addActionListener(this);
		c.gridy = 3;
		c.gridwidth = 1;
		c.weightx = 0.5;
		c.insets = new Insets(15, 0, 0, 5);
		c.fill = GridBagConstraints.NONE;
		c.anchor = GridBagConstraints.EAST;
		add(okayButton, c);

		cancelButton = new JButton("Cancel");
		cancelButton.setPreferredSize(new Dimension(75, 30));
		cancelButton.setMinimumSize(new Dimension(75, 30));
		cancelButton.addActionListener(this);
		c.gridx = 1;
		c.insets = new Insets(15, 5, 0, 0);
		c.anchor = GridBagConstraints.WEST;
		add(cancelButton, c);
	}



	/*******************
	 ** Action Events **
	 *******************/

	public void actionPerformed(ActionEvent evt)
	{
		if (evt.getSource().equals(usernameCheckBox))
		{
			usernameEnable(usernameCheckBox.isSelected());
		}
		else if (evt.getSource().equals(passwordCheckBox))
		{
			passwordEnable(passwordCheckBox.isSelected());			
		}
		else if (evt.getSource().equals(usernameTextField) && !passwordCheckBox.isSelected())
		{
			editUser();
		}
		else if (evt.getSource().equals(passwordField))
		{
			confirmField.requestFocus();
		}
		else if (evt.getSource().equals(okayButton) || evt.getSource().equals(confirmField))
		{
			editUser();
		}
		else if (evt.getSource().equals(cancelButton))
		{
			returnToAdminChoicePane();
		}
	}



	/***************************
	 ** List Selection Events **
	 ***************************/

	public void valueChanged(ListSelectionEvent evt)
	{
		usernameCheckBox.setEnabled(true);
		passwordCheckBox.setEnabled(true);
	}



	/**********************
	 ** Instance Methods **
	 **********************/

	public void initialize()
	{
		try
		{
			Class.forName("org.sqlite.JDBC");
			Connection conn = DriverManager.getConnection("jdbc:sqlite:belief.db");
			Statement statement = conn.createStatement();
			ResultSet rs = statement.executeQuery("SELECT name FROM users");
			ArrayList<String> users = new ArrayList<String>();

			while (rs.next())
			{
				users.add(rs.getString("name"));
			}

			rs.close();
			conn.close();

			Collections.sort(users);

			userList = new DefaultListModel();

			for (int i = 0; i < users.size(); i++)
			{
				userList.addElement(users.get(i));
			}

			userListDisplay.setModel(userList);

			usernameCheckBox.setSelected(false);
			passwordCheckBox.setSelected(false);

			usernameEnable(false);
			passwordEnable(false);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	private void usernameEnable(boolean isEnabled)
	{
		newUsernameLabel.setEnabled(isEnabled);
		usernameTextField.setEnabled(isEnabled);

		if (!isEnabled)
		{
			usernameTextField.setText(null);

			if (!passwordCheckBox.isSelected())
			{
				okayButton.setEnabled(isEnabled);
			}
		}
		else
		{
			okayButton.setEnabled(isEnabled);
			usernameTextField.requestFocus();
		}
	}

	private void passwordEnable(boolean isEnabled)
	{
		newPasswordLabel.setEnabled(isEnabled);
		confirmLabel.setEnabled(isEnabled);
		passwordField.setEnabled(isEnabled);
		confirmField.setEnabled(isEnabled);

		if (!isEnabled)
		{
			passwordField.setText(null);
			confirmField.setText(null);

			if (!usernameCheckBox.isSelected())
			{
				okayButton.setEnabled(isEnabled);
			}
		}
		else
		{
			okayButton.setEnabled(isEnabled);
			passwordField.requestFocus();
		}
	}

	private void editUser()
	{
		if (usernameCheckBox.isSelected())
		{
			if (passwordCheckBox.isSelected())
			{
				if (usernameTextField.getText().equals(""))
				{
					EditUserDialog editUserDialog = new EditUserDialog("Password Error", "nameError", new JOptionPane("Username field is blank. Please try again.", JOptionPane.ERROR_MESSAGE));
				}
				else if (passwordField.getPassword().equals(""))
				{
					EditUserDialog editUserDialog = new EditUserDialog("Password Error", "passError", new JOptionPane("Password field is blank. Please try again.", JOptionPane.ERROR_MESSAGE));
				}
				else if (confirmField.getPassword().equals(""))
				{
					EditUserDialog editUserDialog = new EditUserDialog("Password Error", "confirmError", new JOptionPane("Confirm password field is blank. Please try again.", JOptionPane.ERROR_MESSAGE));
				}
				else
				{
					String password = new String(passwordField.getPassword());
					String confirmedPassword = new String(confirmField.getPassword());

					if (!password.equals(confirmedPassword))
					{
						EditUserDialog editUserDialog = new EditUserDialog("Password Error", "equalsError", new JOptionPane("New password and confirmed password do not match. Please try again.", JOptionPane.ERROR_MESSAGE));
					}
					else
					{
						try
						{
							Class.forName("org.sqlite.JDBC");
							Connection conn = DriverManager.getConnection("jdbc:sqlite:belief.db");
							Statement statement = conn.createStatement();
							String newUsername = usernameTextField.getText();
							ResultSet rs = statement.executeQuery("SELECT name FROM users WHERE name='" + newUsername + "'");

							if (rs.isClosed())
							{
								String username = (String)userListDisplay.getSelectedValue();

								statement.execute("UPDATE users SET name='" + newUsername + "', pass='" + confirmedPassword + "' WHERE name='" + username + "'");

								conn.close();

								EditUserDialog editUserDialog = new EditUserDialog("User Edited", "success", new JOptionPane("User edited successfully.", JOptionPane.INFORMATION_MESSAGE));
							}
							else
							{
								rs.close();
								conn.close();

								EditUserDialog editUserDialog = new EditUserDialog("Username Error", "existsError", new JOptionPane("That username already exists. Please try again.", JOptionPane.ERROR_MESSAGE));
							}
						}
						catch (Exception e)
						{
							e.printStackTrace();
						}
					}
				}
			}
			else
			{
				if (usernameTextField.getText().equals(""))
				{
					EditUserDialog editUserDialog = new EditUserDialog("Password Error", "nameError", new JOptionPane("Username field is blank. Please try again.", JOptionPane.ERROR_MESSAGE));
				}
				else
				{
					try
					{
						Class.forName("org.sqlite.JDBC");
						Connection conn = DriverManager.getConnection("jdbc:sqlite:belief.db");
						Statement statement = conn.createStatement();
						String newUsername = usernameTextField.getText();
						ResultSet rs = statement.executeQuery("SELECT name FROM users WHERE name='" + newUsername + "'");

						if (rs.isClosed())
						{
							String username = (String)userListDisplay.getSelectedValue();

							statement.execute("UPDATE users SET name='" + newUsername + "' WHERE name='" + username + "'");

							conn.close();

							EditUserDialog editUserDialog = new EditUserDialog("User Edited", "success", new JOptionPane("User edited successfully.", JOptionPane.INFORMATION_MESSAGE));
						}
						else
						{
							rs.close();
							conn.close();

							EditUserDialog editUserDialog = new EditUserDialog("Username Error", "existsError", new JOptionPane("That username already exists. Please try again.", JOptionPane.ERROR_MESSAGE));
						}
					}
					catch (Exception e)
					{
						e.printStackTrace();
					}
				}
			}
		}
		else
		{
			if (passwordCheckBox.isSelected())
			{
				if (passwordField.getPassword().equals(null))
				{
					EditUserDialog editUserDialog = new EditUserDialog("Password Error", "passError", new JOptionPane("Password field is blank. Please try again.", JOptionPane.ERROR_MESSAGE));
				}
				else if (confirmField.getPassword().equals(null))
				{
					EditUserDialog editUserDialog = new EditUserDialog("Password Error", "confirmError", new JOptionPane("Confirm password field is blank. Please try again.", JOptionPane.ERROR_MESSAGE));
				}
				else
				{
					String password = new String(passwordField.getPassword());
					String confirmedPassword = new String(confirmField.getPassword());

					if (!password.equals(confirmedPassword))
					{
						EditUserDialog editUserDialog = new EditUserDialog("Password Error", "equalsError", new JOptionPane("New password and confirmed password do not match. Please try again.", JOptionPane.ERROR_MESSAGE));
					}
					else
					{
						try
						{
							String username = (String)userListDisplay.getSelectedValue();
							Class.forName("org.sqlite.JDBC");
							Connection conn = DriverManager.getConnection("jdbc:sqlite:belief.db");

							conn.createStatement().execute("UPDATE users SET pass='" + confirmedPassword + "' WHERE name ='" + username + "'");

							conn.close();

							EditUserDialog editUserDialog = new EditUserDialog("User Edited", "success", new JOptionPane("User edited successfully.", JOptionPane.INFORMATION_MESSAGE));
						}
						catch (Exception e)
						{
							e.printStackTrace();
						}
					}
				}
			}
		}
	}

	private void returnToAdminChoicePane()
	{
		CardLayout mainLayout = (CardLayout)belief.getContentPane().getLayout();

		mainLayout.show(belief.getContentPane(), "adminChoicePane");

		clearFields();
	}

	private void logOut()
	{
		CardLayout mainLayout = (CardLayout)belief.getContentPane().getLayout();

		clearFields();

		mainLayout.show(belief.getContentPane(), "loginPane");
		belief.getLoginPane().getUsernameTextField().requestFocus();
	}

	private void clearFields()
	{
		usernameTextField.setText(null);
		passwordField.setText(null);
		confirmField.setText(null);
		usernameTextField.requestFocus();
	}



	/**********************
	 ** Internal Classes **
	 **********************/

	private class EditUserDialog extends InternalModalDialog
	{
		private String type;

		public EditUserDialog(String title, String type, JOptionPane pane)
		{
			super(title, belief, pane);

			this.type = type;
		}

		public void cleanUpAfterClosing()
		{
			if (type.equals("nameError"))
			{
				usernameTextField.requestFocus();
			}
			else if (type.equals("passError"))
			{
				passwordField.requestFocus();
			}
			else if (type.equals("confirmError"))
			{
				confirmField.requestFocus();
			}
			else if (type.equals("equalsError"))
			{
				passwordField.setText(null);
				confirmField.setText(null);
				passwordField.requestFocus();
			}
			else if (type.equals("existsError"))
			{
				usernameTextField.requestFocus();
			}
			else if (type.equals("success"))
			{
				if (belief.getCurrentUser().equals((String)userListDisplay.getSelectedValue()))
				{
					logOut();
				}
				else
				{
					returnToAdminChoicePane();
				}
			}
		}
	}
}