package org.lyra.Block;

import javax.swing.JPanel;

import java.awt.BorderLayout;
import java.awt.Window;
import java.util.Map;

import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

import org.lyra.AbstractBlock;
import org.lyra.Lyra;


/**
 * Infinite Progress bar which is used to indicate operations of the
 * synchronisation process.   This method should require far less processing
 * time then the full out display.
 * <p>
 * @author Martin Foster
 * @version 1.0.4, %Revision, 150%, %LastChangedDate, 06/11/11 8:56PM%
 * @since 1.0.2
 */
public class InfiniteDialogImpl extends AbstractBlock {

	// Window to block
	private Window Owner;
	
	// Language independent map
	private Map<String,String> Lang;

	// Display element
	private InfiniteDialog infiniteDialog = null;
	
	/**
	 * Identifier for this class allowing us to set it apart from other
	 * implementations which currently exist.
	 */
	public static final String IDENT = "dialog";
	

	/**
	 * Base constructor for the visual editors.  Does not provide any
	 * interactivity capability.
	 * <p>
	 * @param lang Language map.
	 * @param owner Owning component.
	 */
	public InfiniteDialogImpl(Map<String,String> lang, Window owner) {
		
		// Pass Up
		this.Lang  = lang;
		this.Owner = owner;
		
	}
	// End of Constructor Method
	
	
	/**
	 * Creates an instance of InfiniteDialog for blocking and display of the
	 * information display.
	 * <p>
	 * @return org.lyra.Block.InfiniteDialogImpl.InfiniteDialog
	 */
	private InfiniteDialog getInfiniteDialog() {
		
		// Check for Existence
		if (infiniteDialog == null)			
			infiniteDialog = new InfiniteDialog(Owner);
		
		// Return Instance
		return infiniteDialog;
	}
	// End of getInfiniteDialog Method
	
	
	
	/* (non-Javadoc)
	 * @see org.lyra.AbstractBlock#startBlock()
	 */
	public void startBlock() {
		
		// Display and Block
		SwingUtilities.invokeLater(new Runnable() {

			/* (non-Javadoc)
			 * @see java.lang.Runnable#run()
			 */
			public void run() {
				
				// Trigger sync in worker thread
				getInfiniteDialog().setVisible(true);
			}
		});
		
	}
	// End of startBlock method


	/* (non-Javadoc)
	 * @see org.lyra.AbstractBlock#stopBlock()
	 */
	public void stopBlock() {
		
		// Display and Block
		SwingUtilities.invokeLater(new Runnable() {

			/* (non-Javadoc)
			 * @see java.lang.Runnable#run()
			 */
			public void run() {
				
				// Hide and then remove instance
				getInfiniteDialog().setVisible(false);
				
				// Dispose of element
				getInfiniteDialog().dispose();
				
				// Reset instance
				if (infiniteDialog != null)
					infiniteDialog = null;
			}
		});
	}
	// End of stopBlock Method


	/* (non-Javadoc)
	 * @see org.lyra.AbstractBlock#setMessage(java.lang.String)
	 */
	public void setMessage(final String msg) {

		// Update Display Message
		SwingUtilities.invokeLater(new Runnable() {

			
			/* (non-Javadoc)
			 * @see java.lang.Runnable#run()
			 */
			public void run() {
				
				// Update message within queue
				getInfiniteDialog().setMessage(msg);
			}
		});
		
	}
	// End of setMessage Method


	/* (non-Javadoc)
	 * @see org.lyra.AbstractBlock#getMessage()
	 */
	public String getMessage() {

		// Extract Displayed Message
		return getInfiniteDialog().fetchMessage();
	}
	// End of getMessage Method
	
	

	/**
	 * Infinite Progress bar which is used to indicate operations of the
	 * synchronisation process.   This method should require far less processing
	 * time then the full out display.
	 * <p>
	 * @author Martin Foster
	 */
	public class InfiniteDialog extends JDialog {

		// Serial Requirements
		private static final long serialVersionUID = 1L;
		
		// Visual Components
		private JPanel jContentPane = null;
		private JProgressBar displayProgress = null;
		private JLabel iconLyra = null;

		
		/**
		 * Base constructor for this class.  There is no specific constructor
		 * for visual editors due to the lack of capability.
		 * <p>
		 * @param owner Windows owning component.
		 */
		public InfiniteDialog(Window owner) {
			
			// Have super constructor initialise
			super(owner);
			
			// Initialise component
			initDialog(owner);
		}
		// End of Constructor Method
		
		
		/**
		 * This method initialises the baseline look and feel for the dialog
		 * maintaining consistency despite the constructor called.
		 * <p>
		 * @param owner Windows owning component.
		 */
		private void initDialog(Window owner) {

			// Title and Identifier
			this.setTitle(Lang.get("Host.Sync.Window"));
			this.setName("PROGRESS_INFINITE");
			
			// Block parent window
			this.setModal(true);
			
			// Cannot close base window
			this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);

			// Append contents
			this.setContentPane(getJContentPane());
			
			// Pack elements
			this.pack();
			
			// Position
			this.setLocationRelativeTo(owner);
		}
		// End of initDialog Method

		
		/**
		 * This method initialises jContentPane.  Holds all of the actual
		 * components to display.
		 * <p>
		 * @return javax.swing.JPanel
		 */
		private JPanel getJContentPane() {
			
			// Check for Existence
			if (jContentPane == null) {
				
				// Create Instance and Set Layout
				jContentPane = new JPanel();
				jContentPane.setLayout(new BorderLayout());
				
				// Insert Elements
				jContentPane.add(getIconLyra(), BorderLayout.CENTER);
				jContentPane.add(getDisplayProgress(), BorderLayout.SOUTH);
			}
			
			// Return Instance
			return jContentPane;
		}
		// End of getJContentPane

		
		/**
		 * This method initialises displayProgress.  This display bar never
		 * actually shows a progress, the only change will be the message.	
		 * <p>
		 * @return javax.swing.JProgressBar	
		 */
		private JProgressBar getDisplayProgress() {
			
			// Create Instance
			if (displayProgress == null) {
				
				// Create Instance
				displayProgress = new JProgressBar();
				
				// Never Ending Progress
				displayProgress.setIndeterminate(true);
				
				// Always Display Strings
				displayProgress.setString(Lang.get("Host.Sync.Message.Initial"));
				displayProgress.setStringPainted(true);
			}
			
			// Return Instance
			return displayProgress;
		}
		// End of displayProgress Method
	
		
		
		/**
		 * Returns an instance of an icon image which displays the main Lyra
		 * image.   In this case, used to add to the overall dialog and take
		 * up more space.
		 * <p>
		 * @return javax.swing.JLabel
		 */
		private JLabel getIconLyra() {
			
			// Check for Existence
			if (iconLyra == null) {
				
				// Create Instance
				iconLyra = new JLabel(
						new ImageIcon(
							getClass().getResource(
								Lyra.getIconByMap("Lyra-Sync"))));
			}
			
			// Return Instance
			return iconLyra;
			
		}
		// End of getIconLyra Method
		
		
		/**
		 * Adjusts the message being displayed to a newly provided message.
		 * <p>
		 * @param msg String containing new message.
		 */
		public void setMessage(String msg) {
			
			// Pass on the message
			getDisplayProgress().setString(msg);
		}
		// End of setLabelMessage Method
		
		
		/**
		 * Fetches the message being displayed.
		 * <p>
		 * @return String containing current message.
		 */
		public String fetchMessage() {
			
			// Pass on the message
			return getDisplayProgress().getString();
		}
		// End of fetchLabelMessage Method
	}
	// End of InfiniteDialog Class

}
