/**
 * Copyright (c) 2011, Martin Foster <martin@ethereal-realms.org>
 * 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 Ethereal-Realms.org 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 HOLDER 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.lyra.Interface;

import javax.swing.JPanel;
import java.awt.BorderLayout;
import javax.swing.JDialog;
import java.awt.GridLayout;

import javax.swing.Box;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JPasswordField;
import javax.swing.JButton;
import javax.swing.BoxLayout;
import javax.swing.BorderFactory;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import java.awt.Font;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.SwingConstants;
import javax.swing.JCheckBox;

import javax.swing.ImageIcon;
import javax.swing.WindowConstants;

import org.lyra.Ledger;
import org.lyra.Lyra;
import org.lyra.Host.Terminus;
import org.lyra.Listener.WindowSizeListener;
import org.lyra.Widgets.RapidDialog;
import org.lyra.Widgets.RegexConstrainedDocument;
import org.lyra.Widgets.ResizeIcon;

import java.util.HashMap;
import java.util.Map;

/**
 * The ability to create and designate a host for connection.  Since Lyra can
 * support multiple hosts, this screen is separate from the the general
 * settings screen.
 * <p>
 * @author Martin Foster
 * @version 1.0.1, %Revision, 99%, %LastChangedDate, 17/03/11 8:17PM%
 */
public class HostCreateDialog extends JDialog implements Runnable{

	/*
	 * CLASS ELEMENETS
	 * 
	 * Contains variables and structures which the class
	 * requires at a logic point of view.
	 */
	private Map<String,String> Lang;
	private Map<String,String> Host;
	
	// Action and Window Listener
	private Interact Listener;
	
	// Thread
	private Thread Waitor;
	private boolean Process;
	
	/*
	 * PACKAGE ELEMENTS
	 */
	private Ledger Logger;
	private Window Parent;
	
	/*
	 * CLASS ELEMENTS
	 */
	private JDialog myFrame = this;
	
	/*
	 * User Interface Elements:  Section which contains all of the UI
	 * elements which are employed for use on this Dialog.
	 */
	
	// Serial identifier
	private static final long serialVersionUID = 1L;

	// User Interface elements for the display. 
	private JPanel jContentPane = null;
	
	// Element which contains Details, Optional and Actions
	private JPanel panelUser = null;

	// Details Section
	private JPanel panelDetails = null;
	private JLabel labelIdentifier = null;
	private JTextField fieldIdentifier = null;
	private JLabel labelHost = null;
	private JTextField fieldHost = null;
	private JLabel labelPort = null;
	private JTextField fieldPort = null;

	// Optional Password Feature
	private JPanel panelOptional = null;
	private JLabel labelEnable = null;
	private JCheckBox checkEnable = null;
	private JLabel labelPassword = null;
	private JPasswordField fieldPassword = null;

	// Action Elements
	private JPanel panelActions = null;
	private JButton buttonTest = null;
	private JButton buttonSave = null;
	private JButton buttonCancel = null;
	
	// Status Section
	private JPanel panelStatus = null;
	private JLabel iconResize = null;
	
	
	/**
	 * Default constructor class for visual editors.   Not used by the normal
	 * application changeover.
	 */
	@SuppressWarnings("serial")
	private HostCreateDialog() {
		
		/*
		 * Under normal circumstances this section will be passed on from the
		 * database.   However Visual Editors do not have this ability to we
		 * create a HashMap that can be used either way.
		 */
		Lang = new HashMap<String,String>(){
			{
				// Titles and Sections
	        	put("Host.Create.Window.Title","Create a new Multimedia Player Daemon (MPD) Host");
	        	put("Host.Create.Section.Details","Host Details");
	        	put("Host.Create.Section.Help","Help Pane");
	        	
	        	// Widgets
	        	put("Host.Create.Details.Identifier","Site Name");
	        	put("Host.Create.Details.Host","Host Name");
	        	put("Host.Create.Details.Port","Port Number");
	        	put("Host.Create.Options.Enable","Administrative Controls");
	        	put("Host.Create.Options.Password","Password");
	        	
	        	// Tool tips and help
	        	put("Host.Create.Tip.Cancel","Cancel creation of a new host...");
	        	put("Host.Create.Tip.Save","Save Host entry to the database...");
	        	put("Host.Create.Tip.Test","Test Multimedia Player Daemon connection...");
	        	put("Host.Create.Tip.Help","Toggle display of help pane...");
	        	put("Host.Create.Body.Help","Insert a good help section here that should help people with what is necessary.");
	        	
	        	put("Host.Default.Identifier","My Site");
	        	put("Host.Default.Port","6600");
	        	
	        	// Generic features found elsewhere
	        	put("Button.Cancel","Cancel");
	        	put("Button.Save","Save");
	        	put("Button.Test","Test");
	        	put("Button.Help","Help");
			}
		};
		
		// Pass on the bulk creation to a standard method
		initDialog();
	}
	// End of Constructor Method

	
	/**
	 * Default constructor class for visual editors.   Not used by the normal
	 * application changeover.
	 * <p>
	 * @param logger Ledger instance for logging actions.
	 * @param lang Map containing language elements.
	 * @param parent Frame to block.
	 */
	private HostCreateDialog(Ledger logger, Map<String,String> lang, Window parent) {
		
		// Call up the parent
		super(parent);
		
		// Pass up variables
		this.Logger = logger;
		this.Lang = lang;
		
		// Pass up parent
		this.Parent = parent;

		
		// Pass on the bulk creation to a standard method
		initDialog();
	}
	// End of Constructor Method
	
	
	/**
	 * Element which will deal with the creation of the class instance and
	 * extracting the information prior to returning it to the calling program.
	 * <p>
	 * @param logger Ledger instance for logging actions.
	 * @param lang Map containing language elements.
	 * @param parent Frame to block.
	 * @return Map containing host connection details.
	 */
	static public Map<String,String> getHostDetails(Ledger logger, Map<String,String> lang, Window parent) {

		// Create a new instance and make visible
    	HostCreateDialog jd = new HostCreateDialog(logger,lang,parent);
    	
    	// Create a new thread that will wait for a completed Host entry
		jd.Waitor = new Thread(jd);
		jd.Waitor.start();
		
		// Set the display to be visible
    	jd.setVisible(true);
       	
    	// Wait out for our needs
		try {
			// Join in and wait for the results
			jd.Waitor.join();
		} 
		
		catch (InterruptedException e) {
			// Assume something went wrong and assign
			jd.Host = new HashMap<String,String>();
		}
		
		
		/*
		 * Now that we have the managed to make sure that we will be getting a
		 * copy of the hash.  We will close out the window.
		 */
		jd.setVisible(false);
		jd.dispose();
		
		// Return element
		return jd.Host;
	}
	// End of getHostDetails Method
	
	
	/**
	 * This method will wait out until the HashMap is defined.  If not it will
	 * sleep until interrupted.
	 */
	public void run() {
		
		/*
		 * We essentially wait until such a time that the user has opted to 
		 * do something.  Otherwise we have an arbitrarily large sleep period
		 * as to prevent unnecessary cycles.
		 */
		while (Process) {
			try {
				
				// Nothing for us to do sleep
				Thread.sleep(300000);
			} 
			
			/*
			 * Another component has interrupted us from our sleep.  This
			 * should mean the end of the cycle.
			 */
			catch (InterruptedException e) {}
		}
	}
	// End of Run Method
    
	
	/**
	 * This method initialises this
	 */
	private void initDialog() {
		
		// Base Elements
		this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
		this.setTitle(Lang.get("Host.Create.Window.Title"));
		this.setName("CREATE");
		
		// Adjust Icon
		this.setIconImage(Constants.getIcon());
		
		// Create instance of Action handler
		Listener = new Interact(this);
		
		// Set the Window Listener for our use
		this.addWindowListener(Listener);
		
		// Create all of the user elements
		this.setContentPane(getJContentPane());
		
		// Make it optimal for size and centre according to parent
		this.pack();
		
		
		// Set location of dialog and modal behaviour
		if (Parent != null) {
			
			// Adjust Location
			this.setLocationRelativeTo(Parent);
				
			// Block parent window
			this.setModal(true);
		}	
	}
	// End of initDialog Method

	
	/**
	 * This method initialises jContentPane
	 * <p>
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {

		// Determine Existence
		if (jContentPane == null) {

			// Create and establish baseline
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getPanelUser(), BorderLayout.CENTER);
			jContentPane.add(getPanelStatus(), BorderLayout.SOUTH);
		}

		// Return element
		return jContentPane;
	}
	// End of jContentPane Method

	
	/**
	 * This method initialises panelDetails	
	 * <p>	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getPanelDetails() {
		
		// Determine Existence
		if (panelDetails == null) {

			// Establish layout elements
			GridLayout detailsLayout = new GridLayout();
			detailsLayout.setRows(3);
			detailsLayout.setColumns(1);
			
			// Gaps
			detailsLayout.setVgap(Constants.getRowGap());
			
			// Create instance
			panelDetails = new JPanel();
			
			// Layout element
			panelDetails.setLayout(detailsLayout);

			/*
			 * For some rather unusual reason we cannot seem to create varying
			 * sized elements when using a GridLayout.  So we mimic the
			 * operations using Box Layouts.
			 */
			
			// Identifier Section
			panelDetails.add(getPanelRow(
				getLabelIdentifier(),
				getFieldIdentifier()),null
			  );
			
			// Host Name Section
			panelDetails.add(getPanelRow(
				getLabelHost(),
				getFieldHost()),null
			  );
			
			// Port Details
			panelDetails.add(getPanelRow(
				getLabelPort(),
				getFieldPort()),null
			  );
		}
		
		// Return element
		return panelDetails;
	}
	// End of getPanelDetails Method


	
	/**
	 * This method initialises fieldIdentifier	
	 * <p>	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getFieldIdentifier() {

		// Determine Existence
		if (fieldIdentifier == null) {

			// Create verification document
			RegexConstrainedDocument doc = new RegexConstrainedDocument("^[\\w-. ]{0,50}$");
			
			// Create and establish baseline
			fieldIdentifier = new JTextField(doc, Lang.get("Host.Default.Identifier"), 25);
			fieldIdentifier.setName("IDENTIFIER");
		}

		// Return element
		return fieldIdentifier;
	}
	// End of getFieldIdentifier Method

	
	/**
	 * This method initialises fieldHost	
	 * <p>	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getFieldHost() {

		// Determine Existence
		if (fieldHost == null) {

			// Create verification document
			RegexConstrainedDocument doc = new RegexConstrainedDocument("^[\\w-. ]{0,250}$");

			
			// Create and establish baseline
			fieldHost = new JTextField(doc, "", 25);
			fieldHost.setName("HOST");
		}

		// Return element
		return fieldHost;
	}
	// End of getFieldHost Method

	
	/**
	 * This method initialises fieldPort	
	 * <p>	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getFieldPort() {

		// Determine Existence
		if (fieldPort == null) {

			// Create verification document
			RegexConstrainedDocument doc = new RegexConstrainedDocument("\\d{0,5}");
			
			
			// Create and establish baseline
			fieldPort = new JTextField(doc, Lang.get("Host.Default.Port"), 5);
			fieldPort.setName("PORT");
			
			// Adjust Sizing
			fieldPort.setPreferredSize(
				new Dimension(
					fieldPort.getPreferredSize().width + Constants.getPaddingWidth(),
					fieldPort.getPreferredSize().height
				  )
			  );
			
			// Have maximum match
			fieldPort.setMaximumSize(fieldPort.getPreferredSize());
		}

		// Return element
		return fieldPort;
	}
	// End of getFieldPort Method

	
	/**
	 * This method initialises fieldPassword	
	 * <p>	
	 * @return javax.swing.JPasswordField	
	 */
	private JPasswordField getFieldPassword() {

		// Determine Existence
		if (fieldPassword == null) {

			// Create and establish baseline
			fieldPassword = new JPasswordField();
			fieldPassword.setName("PASSWORD");
			fieldPassword.setEnabled(false);
		}

		// Return element
		return fieldPassword;
	}
	// End of getFieldPassword Method
	
	
	/**
	 * This method initialises panelActions	
	 * <p>	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getPanelActions() {

		// Determine Existence
		if (panelActions == null) {

			// Create and establish baseline
			panelActions = new JPanel();
			
			// Layout
			panelActions.setLayout(new BoxLayout(getPanelActions(), BoxLayout.X_AXIS));

			// Insert user elements
			panelActions.add(getButtonTest(), null);
			panelActions.add(getButtonSave(), null);
			panelActions.add(getButtonCancel(), null);
			
			// Spacer to force to the left
			panelActions.add(Box.createHorizontalGlue());
		}

		// Return element
		return panelActions;
	}
	// End of getPanelActions Method

	
	/**
	 * This method initialises buttonTest	
	 * <p>	
	 * @return javax.swing.JButton	
	 */
	private JButton getButtonTest() {

		// Determine Existence
		if (buttonTest == null) {

			// Create and establish baseline
			buttonTest = new JButton();
			buttonTest.setText(Lang.get("Button.Test"));
			buttonTest.setIcon(new ImageIcon(
					Lyra.getIconByMap("Button-Test")));
			buttonTest.setToolTipText(Lang.get("Host.Create.Tip.Test"));
			
			// Establish identifier and listener
			buttonTest.setName("TEST");
			buttonTest.addActionListener(Listener);
		}

		// Return element
		return buttonTest;
	}
	// End of getButtonTest Method

	
	/**
	 * This method initialises buttonSave	
	 * <p>	
	 * @return javax.swing.JButton	
	 */
	private JButton getButtonSave() {

		// Determine Existence
		if (buttonSave == null) {

			// Create and establish baseline
			buttonSave = new JButton();
			buttonSave.setIcon(new ImageIcon(
					Lyra.getIconByMap("Button-Accept")));
			buttonSave.setToolTipText(Lang.get("Host.Create.Tip.Save"));
			buttonSave.setText(Lang.get("Button.Save"));
			
			// Establish identifier and listener
			buttonSave.setName("SAVE");
			buttonSave.addActionListener(Listener);
		}

		// Return element
		return buttonSave;
	}
	// End of getButtonSave Method

	
	/**
	 * This method initialises buttonCancel	
	 * <p>	
	 * @return javax.swing.JButton	
	 */
	private JButton getButtonCancel() {

		// Determine Existence
		if (buttonCancel == null) {

			// Create and establish baseline
			buttonCancel = new JButton();
			buttonCancel.setIcon(new ImageIcon(
					Lyra.getIconByMap("Button-Cancel")));
			buttonCancel.setToolTipText(Lang.get("Host.Create.Tip.Cancel"));
			buttonCancel.setText(Lang.get("Button.Cancel"));
			
			// Establish identifier and listener
			buttonCancel.setName("CANCEL");
			buttonCancel.addActionListener(Listener);
		}

		// Return element
		return buttonCancel;
	}
	// End of getButtonCancel Method

	
	/**
	 * This method initialises panelUser	
	 * <p>	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getPanelUser() {

		// Determine Existence
		if (panelUser == null) {

			// Create and establish baseline
			panelUser = new JPanel();
			
			// Establish layout and border
			panelUser.setLayout(new BoxLayout(getPanelUser(), BoxLayout.Y_AXIS));
			panelUser.setBorder(BorderFactory.createTitledBorder(null, Lang.get("Host.Create.Section.Details"), TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, new Font("Dialog", Font.BOLD, 12), new Color(51, 51, 51)));

			// Primary non-optional details
			panelUser.add(Box.createVerticalGlue());
			panelUser.add(getPanelDetails(), null);
			
			// Optional password handling
			panelUser.add(Box.createVerticalStrut(Constants.getSectionGap()));
			panelUser.add(getPanelOptional(), null);
			
			// Control options
			panelUser.add(Box.createVerticalStrut(Constants.getSectionGap()));
			panelUser.add(getPanelActions(), null);
		}

		// Return element
		return panelUser;
	}
	// End of getPanelUser Method
	

	/**
	 * This method initialises panelOptional	
	 * <p>
	 * @return javax.swing.JPanel	
	 */
	private JPanel getPanelOptional() {
		
		// Verify existence
		if (panelOptional == null) {

			// Establish layout elements
			GridLayout optionalLayout = new GridLayout();
			optionalLayout.setRows(2);
			optionalLayout.setColumns(1);
			
			// Gaps
			optionalLayout.setVgap(Constants.getRowGap());

			// Establish panel elements
			panelOptional = new JPanel();
			
			// Establish layout
			panelOptional.setLayout(optionalLayout);
			
			/*
			 * For some rather unusual reason we cannot seem to create varying
			 * sized elements when using a GridLayout.  So we mimic the
			 * operations using Box Layouts.
			 */
			
			// Enabling/Disabling Checkbox
			panelOptional.add(getPanelRow(
				getLabelEnable(),
				getCheckEnable()),null
			  );
			
			// Password Section
			panelOptional.add(getPanelRow(
					getLabelPassword(),
					getFieldPassword()),null
				  );
		}
		
		// Return generated element
		return panelOptional;
	}
	// End of getPanelOptional Method

	
	/**
	 * This method initialises checkEnable	
	 * <p>
	 * @return javax.swing.JCheckBox	
	 */
	private JCheckBox getCheckEnable() {

		// Determine Existence
		if (checkEnable == null) {

			// Create and establish baseline
			checkEnable = new JCheckBox();
			
			// Identifier and Listener
			checkEnable.setName("ENABLE");
			checkEnable.addChangeListener(Listener);
		}

		// Return element
		return checkEnable;
	}
	// End of getCheckEnable Method
	
	
	/**
	 * This method initialises iconResize
	 * <p>
	 * @return javax.swing.JLabel
	 */
	private JLabel getIconResize() {
		
		// Verify existence of element
		if (iconResize == null) {

			// Create and establish baseline
			iconResize = new JLabel(new ResizeIcon());
			iconResize.setOpaque(false);
			
			/*
			 * Making this icon do something of use is one of the core reasons
			 * why it was added to the display itself.  Here we create an 
			 * instance and add the listener, since it is not used anywhere else
			 * we don't worry out creating an instance earlier.
			 */
			WindowSizeListener sizer = new WindowSizeListener(this);
			
			// Add in listener elements
			iconResize.addMouseListener(sizer);
			iconResize.addMouseMotionListener(sizer);
		}
		
		// Return label
		return iconResize;
	}
	// End of getIconResize Method
	

	/**
	 * This method initialises labelEnable
	 * <p>
	 * @return javax.swing.JLabel
	 */
	private JLabel getLabelEnable() {
		
		// Verify existence of element
		if (labelEnable == null) {

			// Create and establish baseline
			labelEnable = new JLabel();
			labelEnable.setText(Lang.get("Host.Create.Options.Enable"));
			labelEnable.setHorizontalAlignment(SwingConstants.RIGHT);
		}
		
		// Return label
		return labelEnable;
	}
	// End of getLabelEnable Method

	
	/**
	 * This method initialises labelHost	
	 * <p>
	 * @return javax.swing.JLabel
	 */
	private JLabel getLabelHost() {
		
		// Verify existence of element
		if (labelHost == null) {

			// Create and establish baseline
			labelHost = new JLabel();
			labelHost.setText(Lang.get("Host.Create.Details.Host"));
			labelHost.setHorizontalAlignment(SwingConstants.RIGHT);
		}
		
		// Return label
		return labelHost;
	}
	// End of getLabelHost Method
	
	
	/**
	 * This method initialises labelIdentifier	
	 * <p>
	 * @return javax.swing.JLabel
	 */
	private JLabel getLabelIdentifier() {
		
		// Verify existence of element
		if (labelIdentifier == null) {

			// Create and establish baseline
			labelIdentifier = new JLabel();
			labelIdentifier.setText(Lang.get("Host.Create.Details.Identifier"));
			labelIdentifier.setHorizontalAlignment(SwingConstants.RIGHT);
		}
		
		// Return label
		return labelIdentifier;
	}
	// End of getLabelIdentifier Method
	
	
	/**
	 * This method initialises labelPassword	
	 * <p>
	 * @return javax.swing.JLabel
	 */
	private JLabel getLabelPassword() {
		
		// Verify existence of element
		if (labelPassword == null) {
			
			// Create and establish baseline
			labelPassword = new JLabel();
			labelPassword.setText(Lang.get("Host.Create.Options.Password"));
			labelPassword.setEnabled(false);
			labelPassword.setHorizontalAlignment(SwingConstants.RIGHT);
		}
		
		// Return label
		return labelPassword;
	}
	// End of getLabelPassword Method

	
	/**
	 * This method initialises labelPort	
	 * <p>
	 * @return javax.swing.JLabel
	 */
	private JLabel getLabelPort() {
		
		// Verify existence of element
		if (labelPort == null) {
			
			// Create and establish baseline
			labelPort = new JLabel();
			labelPort.setText(Lang.get("Host.Create.Details.Port"));
			labelPort.setHorizontalAlignment(SwingConstants.RIGHT);
		}
		
		// Return label
		return labelPort;
	}
	// End of getLabelPort Method

	
	/**
	 * This method initialises a JPanel component providing row elements. 
	 * <p>
	 * @param label JLabel instance which will be resized.
	 * @param widget JComponent instance which will be added as-is.
	 * @return JPanel containing the elements properly established.
	 */
	private JPanel getPanelRow(JLabel label, JComponent widget) {
		
		/*
		 * In order to create a consistent look and feel with our use of 
		 * BoxLayout we will resize all the elements from this point.  However
		 * we maintain Height as to adjust if there are font changes.
		 */
		label.setPreferredSize(
			new Dimension(
				Constants.getLabelWidth(),
				label.getPreferredSize().height)
		  );
		
		/*
		 * Here we adjust the maximum values to be suitable for our needs.  
		 * Essentially we are not looking for text fields to grow exponentially
		 * when a user resizes itself.
		 */
		widget.setMaximumSize(
			new Dimension(
				widget.getMaximumSize().width,
				widget.getPreferredSize().height + Constants.getPaddingHeight())
		  );
		
		/*
		 * We create the element at this point.  We essentially throw all
		 * of the instances into a newly created section and call it the
		 * end of a day.
		 */
		
		// Create instance
		JPanel row = new JPanel();

		// Establish layout
		row.setLayout(new BoxLayout(row, BoxLayout.X_AXIS));
		
		// Insertion of the label and spacer
		row.add(label);
		row.add(Box.createHorizontalStrut(Constants.getLabelSpacer()));
		
		// Insertion of the widget and end spacer
		row.add(widget);
		row.add(Box.createHorizontalGlue());
		
		// Pass on row
		return row;
	}
	// End of getPanelRow Method
	
	
	/**
	 * This method initialises panelStatus	
	 * <p>
	 * @return javax.swing.JPanel	
	 */
	private JPanel getPanelStatus() {
		
		// Determine existence
		if (panelStatus == null) {

			// Create instance
			panelStatus = new JPanel();
			
			// Establish layout
			panelStatus.setLayout(new BoxLayout(getPanelStatus(), BoxLayout.X_AXIS));
			
			// Add in resizing label/icon
			panelStatus.add(Box.createHorizontalGlue());
			panelStatus.add(getIconResize(), null);
		}
		
		// Return instance
		return panelStatus;
	}
	// End of getPanelStatus
	
	
    /**
     * A class dedicated to the action handling for the org.lyra.Host.Create'
     * class.  Since there is no real code re-use beyond the implementation it
     * was placed as a sub-class for code segregation.
     * <p>
     * @author Martin Foster
     *
     */
    private class Interact implements ActionListener, WindowListener, ChangeListener {

    	/*
    	 * VARIABLES
    	 */
    	private JDialog Caller;
    	private RapidDialog Notify;
    	
    	/*
    	 * CONSTANTS
    	 */
    	private static final String CLASS = "org.lyra.Interface.HostCreateDialog.Interact";
    	
    	/**
    	 * Base constructor which provides the calling Class ability to grant
    	 * access to its windowing capability.  Such as window size.
    	 * <p>
    	 * @param caller JDialog instance.
    	 */
    	public Interact(JDialog caller) {
    		// Pass up
    		this.Caller = caller;
    		
    		// Create instance of the dialog generator
    		Notify = new RapidDialog(Lang);
    	}
    	// End of Constructor Class
    	
    	
    	/*
    	 * STATE EVENTS
    	 */
    	
		/* (non-Javadoc)
		 * @see java.awt.event.ChangeListener#stateChanged(java.awt.event.stateChanged)
		 */
		public void stateChanged(ChangeEvent evt) {
			
			/*
			 * The check box is easy as it is tied directly to the state.  Change
			 * in state results in a change in enabling of the password section.
			 */
			if (evt.getSource() instanceof JCheckBox) {
				// Fetch Element and State
				JCheckBox box = (JCheckBox)evt.getSource();
				boolean state = box.isSelected();
				
				// Pass on the state directly
				getFieldPassword().setEnabled(state);
				getLabelPassword().setEnabled(state);
				
				// Log the action
				Logger.Info(
					CLASS, 
					"stateChanged",
					Lang.get("Host.Log.State.Password").replaceAll("MSTATE", Boolean.toString(state))
				  );
			}
			
		}
		// End of stateChanged Method
    	
    	/*
    	 * ACTION BASED EVENTS
    	 */
    	
    	
		/* (non-Javadoc)
		 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
		 */
		@SuppressWarnings("serial")
		public void actionPerformed(ActionEvent evt) {
			
			/*
			 * A quick safety check to make sure we are dealing with the
			 * appropriate type.  When that has been confirmed we will extract
			 * the name and use that to determine appropriate action.
			 */
			if (evt.getSource() instanceof JComponent) {
				
				// Cast to a JButton Instance
				String ident = ((JComponent)evt.getSource()).getName();
				
				// Determine what was pressed
				// User has opted to Save
				if (ident.equals(getButtonSave().getName())) {
					
					/*
					 * Create the Key/Value pairs for a new HashMap which will
					 * contain all of the information necessary to create a new
					 * host.
					 */
					Host = new HashMap<String,String>(){
						{
							// Titles and Sections
				        	put("Identifier",getFieldIdentifier().getText());
				        	put("Host",getFieldHost().getText());
				        	put("Port",getFieldPort().getText());
						}

					};
					
					/*
					 * Passwords are a unique element, so we deal with them
					 * differently.  If the password box is checked we pass
					 * on the element without checks, no our concern if it
					 * failed.
					 */
					if (getCheckEnable().isSelected()) {
						// Here we create the full entry and translate
						Host.put(
							"Password",
							String.valueOf(getFieldPassword().getPassword())
						  );
					}
					
					else {
						// We return null with the string built up
						Host.put("Password",null);
					}
					
					
					// Log the action
					Logger.Info(
						CLASS, 
						"actionPerformed",
						Lang.get("Host.Log.Action.Save").replaceAll("MHOST",Host.toString())
					  );
					
					// End Processing
					Process = false;
					
					// Hide and dispose of window
					myFrame.setVisible(false);
					myFrame.dispose();
					
					// Interrupt thread
					Waitor.interrupt();
				}
			
				// User has opted to cancel
				else if (ident.equals(getButtonCancel().getName())) {
					/*
					 * All we do is pass on the necessary HashMap even though
					 * it is empty.  That will be the check to be done once it
					 * is returned.
					 */
					Host = new HashMap<String,String>();
					
					// Log the action
					Logger.Info(
						CLASS, 
						"ActionPerformed",
						Lang.get("Host.Log.Action.Cancel")
					  );
					
					// End Processing
					Process = false;
					
					// Hide and dispose of window
					myFrame.setVisible(false);
					myFrame.dispose();
					
					// Interrupt thread
					Waitor.interrupt();
				}
				
				// User has opted to test the connection
				if (ident.equals(getButtonTest().getName())) {
					
					/*
					 * Create the Key/Value pairs for a new HashMap which will
					 * contain all of the information necessary to test the
					 * host connection.
					 */
					Map<String,String> test = new HashMap<String,String>(){
						{
							// Titles and Sections
				        	put("Host",getFieldHost().getText());
				        	put("Port",getFieldPort().getText());
						}

					};
					
					/*
					 * Passwords are a unique element, so we deal with them
					 * differently.  If the password box is checked we pass
					 * on the element without checks, no our concern if it
					 * failed.
					 */
					if (getCheckEnable().isSelected()) {
						// Here we create the full entry and translate
						test.put(
							"Password",
							String.valueOf(getFieldPassword().getPassword())
						  );
					}
					
					else {
						// We return null with the string built up
						test.put("Password",null);
					}
					
					
					// Log the action
					Logger.Info(
						CLASS, 
						"actionPerformed",
						Lang.get("Host.Log.Action.Test").replaceAll("MHOST",test.toString())
					  );
					
					
					/*
					 * Now that we have generated the entries for testing we
					 * can create an instance of org.Lyra.Terminus and actually
					 * test its effectiveness.
					 */
					Terminus trial = new Terminus(
						Logger, 
						test.get("Host"),
						test.get("Port"),
						test.get("Password")
					  );
					
					// Attempt to make a connection
					if (trial.Connect()) {
						
						// Connection has passed so fail
						trial.Disconnect();
						
						// Log the action
						Logger.Info(
							CLASS, 
							"actionPerformed",
							Lang.get("Host.Log.Action.Test.Pass")
						  );
						
						/*
						 * We need to notify the user about the status so we
						 * need to generate a string for their use.
						 */
						String msg = Lang.get("Host.Create.Dialog.Test.Pass");
						msg = msg.replaceAll("MHOST", test.get("Host"));
						msg = msg.replaceAll("MPORT", test.get("Port"));

						// Display Message
						Notify.noticePass(Caller, msg);
					}
					
					else {
						// Log the action
						Logger.Info(
							CLASS, 
							"actionPerformed",
							Lang.get("Host.Log.Action.Test.Fail")
						  );
						
						/*
						 * We need to notify the user about the status so we
						 * need to generate a string for their use.
						 */
						String msg = Lang.get("Host.Create.Dialog.Test.Fail");
						msg = msg.replaceAll("MHOST", test.get("Host"));
						msg = msg.replaceAll("MPORT", test.get("Port"));

						// Display Message
						Notify.noticeFail(Caller, msg);
					}
				}
			}
		}
		// End of actionPerformed Method
		
    	
    	/*
    	 * WINDOW BASED EVENTS
    	 */
		
		/* (non-Javadoc)
		 * @see java.awt.event.WindowListener#windowClosing(java.awt.event.WindowEvent)
		 */
		public void windowClosing(WindowEvent evt) {
			
			/*
			 * There are plenty of elements that have to be confirmed when
			 * someone ignores the buttons and just closes the dialog.  So what
			 * we do is make sure that a proper state can be returned.
			 */	
			if (Host == null) {
				Host = new HashMap<String,String>();
				
				// Log the action
				Logger.Info(
					CLASS, 
					"ActionPerformed",
					Lang.get("Host.Log.Action.Cancel")
				  );
				
				// End Processing
				Process = false;
				
				// Hide and dispose of window
				myFrame.setVisible(false);
				myFrame.dispose();
				
				// Interrupt thread
				Waitor.interrupt();
			}
		
		}
		// End of windowClosing Method

		
		/* (non-Javadoc)
		 * @see java.awt.event.WindowListener#windowClosed(java.awt.event.WindowEvent)
		 */
		public void windowClosed(WindowEvent evt) {}
		
    	
		/* (non-Javadoc)
		 * @see java.awt.event.WindowListener#windowActivated(java.awt.event.WindowEvent)
		 */
		public void windowActivated(WindowEvent evt) {}



		
		/* (non-Javadoc)
		 * @see java.awt.event.WindowListener#windowDeactivated(java.awt.event.WindowEvent)
		 */
		public void windowDeactivated(WindowEvent evt) {}


		/* (non-Javadoc)
		 * @see java.awt.event.WindowListener#windowDeiconified(java.awt.event.WindowEvent)
		 */
		public void windowDeiconified(WindowEvent evt) {}


		/* (non-Javadoc)
		 * @see java.awt.event.WindowListener#windowIconified(java.awt.event.WindowEvent)
		 */
		public void windowIconified(WindowEvent evt) {}


		/* (non-Javadoc)
		 * @see java.awt.event.WindowListener#windowOpened(java.awt.event.WindowEvent)
		 */
		public void windowOpened(WindowEvent evt) {}
    }
    // End of Action Class
    
}
