/* File: AddNodesDialog.java
 * Author: Jason Gookins
 * Description: This class creates the popup dialog for adding multiple nodes to the network at once.
 */

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyVetoException;
import java.util.ArrayList;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;

public class AddNodesDialog extends JInternalFrame implements ActionListener
{
	/************************
	 ** Instance Variables **
	 ************************/

	private Belief belief;
	private ArrayList<Node> nodes;
	private JTextField newNodeTextField;
	private JButton addButton;
	private JButton removeButton;
	private DefaultListModel newNodesList;
	private JList newNodesListDisplay;
	private JButton okayButton;
	private JButton cancelButton;
	private String[] newNodes;



	/**********************
	 ** Main Constructor **
	 **********************/

	public AddNodesDialog(Belief belief, ArrayList<Node> nodes)
	{
		super("Add Nodes", false, false, false, false);

		this.belief = belief;
		this.nodes = nodes;

		setPreferredSize(new Dimension(300, 300));

		JPanel dialogPanel = new JPanel(null);

		JLabel newNodeLabel = new JLabel("New Node:", JLabel.CENTER);
		newNodeLabel.setBounds(10, 45, 125, 20);
		dialogPanel.add(newNodeLabel);

		newNodeTextField = new JTextField();
		newNodeTextField.setBounds(15, 70, 125, 20);
		dialogPanel.add(newNodeTextField);

		addButton = new JButton("Add >>");
		addButton.setBounds(20, 100, 115, 30);
		addButton.addActionListener(this);
		dialogPanel.add(addButton);
		getRootPane().setDefaultButton(addButton);

		removeButton = new JButton("Remove <<");
		removeButton.setBounds(20, 140, 115, 30);
		removeButton.addActionListener(this);
		dialogPanel.add(removeButton);

		newNodesList = new DefaultListModel();

		newNodesListDisplay = new JList(newNodesList);
		newNodesListDisplay.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		JScrollPane listScrollPane = new JScrollPane(newNodesListDisplay, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		listScrollPane.setBounds(150, 15, 135, 200);
		dialogPanel.add(listScrollPane);

		okayButton = new JButton("Okay");
		okayButton.setBounds(60, 230, 75, 25);
		okayButton.addActionListener(this);
		dialogPanel.add(okayButton);

		cancelButton = new JButton("Cancel");
		cancelButton.setBounds(165, 230, 75, 25);
		cancelButton.addActionListener(this);
		dialogPanel.add(cancelButton);

		setContentPane(dialogPanel);

		putClientProperty("JInternalFrame.frameType", "optionDialog");

		Dimension size = getPreferredSize();
		Dimension rootSize = belief.getRootPane().getSize();

		setBounds((rootSize.width - size.width) / 2, (rootSize.height - size.height) / 2, size.width, size.height);

		pack();
		belief.getFirstEventPane().setVisible(true);
		setVisible(true);
		belief.getLayeredPane().add(this, new Integer(1));

		try
		{
			setSelected(true);
		}
		catch (PropertyVetoException ignored) { }

		focusNewNodeTextField();
	}



	/***************
	 ** Accessors **
	 ***************/

	public String[] getNewNodes()
	{
		return this.newNodes;
	}



	/*******************
	 ** Action Events **
	 *******************/

	public void actionPerformed(ActionEvent evt)
	{
		if (evt.getSource().equals(addButton))
		{
			addNodeToListDisplay();
		}
		else if (evt.getSource().equals(removeButton))
		{
			removeNodeFromListDisplay();
		}
		else if (evt.getSource().equals(okayButton))
		{
			populateNodeList();

			cleanUpAndDispose();
		}
		else if (evt.getSource().equals(cancelButton))
		{
			cleanUpAndDispose();
		}
	}



	/**********************
	 ** Instance Methods **
	 **********************/

	private void focusNewNodeTextField()
	{
		SwingUtilities.invokeLater(new Runnable()
		{
			public void run()
			{
				newNodeTextField.requestFocus();
				newNodeTextField.selectAll();
			}
		});
	}

	private void addNodeToListDisplay()
	{
		String newNodeName = newNodeTextField.getText();

		if (newNodeName != null)
		{
			if (newNodeName.length() > 0)
			{
				boolean nameExists = false;

				for (Node node : nodes)
				{
					if (newNodeName.compareToIgnoreCase(node.getName()) == 0)
					{
						nameExists = true;

						break;
					}
				}

				if (!nameExists)
				{
					for (int i = 0; i < newNodesList.size(); i++)
					{
						String nodeName = newNodesList.get(i).toString();

						if (newNodeName.equals(nodeName))
						{
							nameExists = true;

							break;
						}
					}

					if (!nameExists)
					{
						newNodesList.addElement(newNodeTextField.getText());
						newNodeTextField.setText(null);
					}
					else
					{
						ErrorDialog errorDialog = new ErrorDialog("Node Name Error", new JOptionPane("You are already trying to add a node with that name. Please try again.", JOptionPane.ERROR_MESSAGE));
					}
				}
				else
				{
					ErrorDialog errorDialog = new ErrorDialog("Node Exists Error", new JOptionPane("A node with that name already exists. Please try again.", JOptionPane.ERROR_MESSAGE));
				}
			}
		}
	}

	private void removeNodeFromListDisplay()
	{
		int[] indices = newNodesListDisplay.getSelectedIndices();

		if (indices.length > 0)
		{
			newNodesList.removeRange(indices[0], indices[indices.length - 1]);
		}
	}

	private void populateNodeList()
	{
		newNodes = new String[newNodesList.size()];

		for (int i = 0; i < newNodesList.size(); i++)
		{
			newNodes[i] = newNodesList.get(i).toString();
		}
	}

	private void cleanUpAndDispose()
	{
		dispose();

		if (newNodes != null)
		{
			belief.getBeliefListener().addNodes(newNodes);
		}

		belief.getFirstEventPane().setVisible(false);
	}



	/**********************
	 ** Internal Classes **
	 **********************/

	private class ErrorDialog extends InternalModalDialog
	{
		public ErrorDialog(String title, JOptionPane pane)
		{
			super(title, belief, pane);
		}

		public void cleanUpAfterClosing()
		{
			focusNewNodeTextField();
		}
	}
}