/*******************************************************************************
* Copyright (c)                                                                *
*           2005   Tristan Allwood,                                            *
*           2005   Daniel Burke,                                               *
*           2005   Marc Hull,                                                  *
*           2005   Ekaterina Itskova,                                          *
*           2005   Steve Zymler                                                *
*                                                                              *
* Permission is hereby granted, free of charge, to any person obtaining a      *
* copy of this software and associated documentation files (the                *
* "Software"), to deal in the Software without restriction, including          *
* without limitation the rights to use, copy, modify, merge, publish,          *
* distribute, sublicense, and/or sell copies of the Software, and to           *
* permit persons to whom the Software is furnished to do so, subject to        *
* the following conditions:                                                    *
*                                                                              *
* The above copyright notice and this permission notice shall be included      *
* in all copies or substantial portions of the Software.                       *
*                                                                              *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS      *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF                   *
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.       *
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY         *
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,         *
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE            *
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                       *
*******************************************************************************/
/*
 * Created on 03-Nov-2004
 *
 */
package uk.ac.ic.doc.kevlar.gui.internal.help;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;

import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;

import uk.ac.ic.doc.kevlar.api.programs.arguments.IArgumentHelp;
import uk.ac.ic.doc.kevlar.api.programs.arguments.internal.iomapping.INodeHelp;
import uk.ac.ic.doc.kevlar.core.framework.IProgramIDDescription;
import uk.ac.ic.doc.kevlar.gui.internal.AMouseListenerObject;
import uk.ac.ic.doc.kevlar.gui.internal.CanvasManager;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.KeyboardManager;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.states.HelpState;
import uk.ac.ic.doc.kevlar.publicInterfaces.IProgramDescription;

/**
 * @author Kate
 *
 */

public class HelpManager extends AMouseListenerObject {
	
	private final int helpWidth = 232;
	private final int helpHeight = 150;
	private static HelpManager singleton;
	private Browser helpDisplay;
	private boolean helpDisplayed;
	
	private String helpHeader;
	private String helpFooter;
	private final String separator = "<tr><td id='separator'></td></tr>";
	
	private HelpManager(Composite c)
	{
		helpDisplay = new Browser(c, SWT.SIMPLE);
		helpDisplay.addKeyListener(KeyboardManager.getSingleton());
		helpDisplayed = false;
		initializeResources();
	}
	
	private void initializeResources()
	{
	    String path = System.getProperty("KEVLAR_HTML_BASE");
	    URL cssFile;
	    URL topImage;
	    URL bottomImage;
	    
	    if( path == null ) {
	        cssFile = HelpManager.class.getResource("help.css");
	        topImage = HelpManager.class.getResource("top.png");
	        bottomImage = HelpManager.class.getResource("bottom.png");
	    } else {
	        try {
	        cssFile = new URL("file://" + path + File.separator + "help.css");
	        topImage = new URL("file://" + path + File.separator + "top.png");
	        bottomImage = new URL( "file://" +path + File.separator + "bottom.png");
	        } catch(MalformedURLException mue ) {
	            throw new Error(mue);
	        }
	    }
		
		helpHeader = "<html><head><link rel= 'stylesheet'" +
					 " type='text/css' href='"+cssFile+"'/></head>" +
					 "<body><img src='"+topImage+"'><table><tr><td><p id='heading'><b>";
		
		
		helpFooter = "<img src='"+bottomImage+"'></body></html>";
	}
	
	public static void createSingleton(Composite c)
	{
		if (singleton==null)
		{
			singleton = new HelpManager(c);
		}
	}
	
	public static HelpManager getSingleton()
	{
		return singleton;
	}
	
	public void display() {
	    	    
	    if (!helpDisplayed) {
	    
	        helpDisplay.setVisible(true);
	        helpDisplayed = true;
	        getMouseFocus();
	        KeyboardManager.getSingleton().setState(new HelpState());
	        
	    }
	    
	}
	
	public void mousePress(Point position, int button) {
	    
	    Rectangle helpArea = helpDisplay.getBounds();
	    
	    if (!helpArea.contains(position)) {
	        
	        hideHelp();
	        
	    }
	    
	}
	
	public void displayArgumentHelp(String name, IArgumentHelp help, int x, int y, int offset)
	{
		helpDisplay.setVisible(false);
		int canvasY = CanvasManager.getSingleton().getArea().height;
		int canvasX = CanvasManager.getSingleton().getArea().width;
		if (y+helpHeight > canvasY)
		{
			y = canvasY-helpHeight;
		}
		
		if (x+helpWidth>canvasX)
		{
			x = offset-helpWidth;
		}
		
		helpDisplay.setBounds(new Rectangle(x,y, helpWidth, helpHeight));
		helpDisplay.setText(layoutArgumentHelp(name, help));

/*		helpDisplay.setVisible(true);
		helpDisplayed = true; */
		
		display();
		
	}
	
	public void displayIONodeHelp(String name, INodeHelp help, int x, int y, int offset)
	{
		helpDisplay.setVisible(false);
		int canvasY = CanvasManager.getSingleton().getArea().height;
		int canvasX = CanvasManager.getSingleton().getArea().width;
		
		if (y+helpHeight > canvasY)
		{
			y = canvasY-helpHeight;
		}
		
		if (x+helpWidth>canvasX)
		{
			x = offset - helpWidth;
		}
		
		
		
		helpDisplay.setBounds(new Rectangle(x,y, helpWidth, helpHeight));
		
		helpDisplay.setText(layoutIONodesHelp(name, help));
		
/*		helpDisplay.setVisible(true);
		helpDisplayed = true; */
		
		display();

	}
	
	public void displayProgramHelp(IProgramIDDescription desc, int x, int y)
	{
		helpDisplay.setVisible(false);
		int canvasY = CanvasManager.getSingleton().getArea().height;
		if (y+helpHeight > canvasY)
		{
			y = canvasY-helpHeight;
		}
		
		helpDisplay.setBounds(new Rectangle(x,y, helpWidth, helpHeight));
		helpDisplay.setText(layoutProgramHelp(desc));
		
/*		helpDisplay.setVisible(true);
		helpDisplayed = true; */
		
		display();
		
	}
	
	public void hideHelp()
	{
	    
	    if (helpDisplayed) {
	    
	        helpDisplay.setVisible(false);
	        helpDisplayed = false;
	        releaseMouseFocus();
	        
	        if (KeyboardManager.getSingleton().getState() instanceof HelpState) {
	            
	            KeyboardManager.getSingleton().gotoHistoryState();
	            
	        }
	        
	    }
	    
	}
	
	public int getWidth()
	{
		return helpWidth;
	}
	
	private String layoutProgramHelp(IProgramDescription desc)
	{	
		/* generates html code, which is the format the help is displayed */
		
		String display = helpHeader;
		
/*		display += desc.getFriendlyName()+"</p></td></tr>" +
				separator+"<tr><td>" +
				"<p id='heading'>Version "+desc.getMajorVersion()+"."+desc.getMinorVersion()+
				"</p></td></tr>"+separator; */
		
		display += desc.getFriendlyName()+"</b> (v"+desc.getMajorVersion()+"."+desc.getMinorVersion()+
		")</p></td></tr>"+separator;

		if (desc.getAuthor() != null || desc.getCopyrightOwner() != null || desc.getCopyrightYear() != 0) {
		
		    if (desc.getAuthor() != null) {
		    
		        display +="<tr><td><p id='heading'><b>Author:</b> "+desc.getAuthor()+ "</p></td></tr>";
		        
		    }
		    
		    if (desc.getCopyrightOwner() != null) {
		    
		        display += "<tr><td><p id='heading'><b>Copyright owner:</b> "+desc.getCopyrightOwner()+"</p></td></tr>";
		        
		    }
		    
		    if (desc.getCopyrightYear() != 0) {
		        
		        display += "<tr><td><p id='heading'><b>Copyright year:</b> "+desc.getCopyrightYear()+"</p></td></tr>";
		        
		    }
		    
		    display += separator;
		
		}
		    
		display +="<tr><td><p id='heading'><b>Program description:</b></p></td></tr>" +
				"<tr> <td><blockquote><p id='text'>"+desc.getDescription()+"</p></blockquote></td>" +
				"</tr>"+separator;
		
		if (desc.getWebsite() != null && !desc.getWebsite().equals("")) {
		
		    String website = desc.getWebsite().toString();
		    
		    display +="<tr><td><p id='heading'><b>Website:</b></p></td></tr>" +
					"<tr><td><p id='text'><a href="+website+" target='_new'>";
		    
		    while (website.length() > 0) {
		        
		        if (website.length()>35) {
		            
		            display += website.substring(0, 35)+"<BR>";
		            website = website.substring(35);
		            
		        } else {
		            
		            display += website;
		            website = "";
		            
		        }
		        
		    }
		    
		    display +="</a></p>" +
					"</td></tr>"+separator;
		    
		}
		
		if (desc.getKeywords().size() > 0) {
		
		    display +="<tr><td><p id='heading'><b>Keywords:</b></p></td></tr><tr><td><blockquote><p id='text'>";
		
		    Iterator keywords = desc.getKeywords().iterator();
		    while(keywords.hasNext())
			{
		        String keyword = (String)keywords.next();
		        display += keyword+" ";
			}	
		    display +="</p></blockquote></td></tr></table>";
		    
		}
//		display += helpFooter;	
		return display;
	}
	
	private String layoutArgumentHelp(String name, IArgumentHelp help)
	{
		/*generate html to display arguments help */
		
		String display = helpHeader;
		display += name+"</p></td></tr>"+separator;
		display += "<tr><td><p id='heading'><b>Argument Overview:</b></p></td></tr>" +
				"<tr><td><blockquote><p id='text'>"+help.getOverviewMessage()+
				"</p></blockquote></td></tr>";
		
		if (help.hasValidationMessage())
		{
			display += separator+"<tr><td><p id='heading'><b>Validation message</b></p>" +
					"</td></tr><tr><td><blockquote><p id='text'>" +
					help.getValidationMessage()+"</p></blockquote></td></tr></table>";
		}
		//display += helpFooter;
		return display;
	}
	
	private String layoutIONodesHelp(String name, INodeHelp help)
	{
		/* generates html to display I/O nodes help */
		
		String display = helpHeader;
		display += name+"</p></td></tr>"+separator;
		display += "<tr><td><p id='heading'><b>Node Overview:</b></p></td></tr>" +
				"<tr><td><blockquote><p id='text'>"+help.getOverview()+
				"</p></blockquote></td></tr></table>";
		
		//display += helpFooter;
		return display;
	}
	
	public boolean isDisplayed()
	{
		return helpDisplayed;
	}

}
