package gui;

import java.io.File;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.OpenWindowListener;
import org.eclipse.swt.browser.WindowEvent;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Shell;
import other.PathHelp;
 
/**
 * ToolTipHandler Klasse 
 * Verwaltet die Tooltips die die Informationen zu den
 * einzelnen Kommandos anzeigen
 */
public class ToolTipHandler {
	
	// Attribute
	private Shell sShell = null;
	private Browser browser = null;
	private Point pPos = null;
	private TabItemProgram tabItemPrg = null;
	private int strLine;

	/**
	 * Konstruktor.
	 * @param parent übergeordnete Shell
	 */
    public ToolTipHandler(Shell parent, TabItemProgram tabItemParent) {
    	tabItemPrg = tabItemParent;
        sShell = new Shell(parent, SWT.ON_TOP | SWT.TOOL);
        sShell.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
        sShell.setSize(300, 100);
        sShell.setLayout(new FillLayout());
		browser = new Browser(sShell, SWT.NONE);
		browser.setBounds(sShell.getClientArea());
	    browser.addOpenWindowListener(new OpenWindowListener() {
	    	// Für JavaScript-Aufrufe window.open()
	        public void open(WindowEvent event) {
	        	// Öffnen des Fensters abbrechen
	        	event.required=true; 
	        	// ToolTip schließen
	        	checkVisibleAndClose();
	        	// Aufruf nach oben weiterleiten
	        	tabItemPrg.windowOpenEvent(browser.getUrl().substring(browser.getUrl().lastIndexOf("/")+1),strLine);
	        }
	      });
    }
	
	/* ##########################################################################
	 * 						ÖFFENTLICHE METHODEN
	 * ##########################################################################*/
    
    /**
     * Schaltet die Überwachung ein
     * @param styledText die zu überwachende Textbox
     */
    public void activateHoverHelp(StyledText styText){
    	
    	// Listener installieren
    	// MouseDown: Klick schließt Fenster
    	styText.addMouseListener(new MouseAdapter() {
            public void mouseDown(MouseEvent e) {
            	checkVisibleAndClose();
            }
    	});
    	// MouseMove: Bewegung schließt Fenster
    	styText.addMouseMoveListener(new org.eclipse.swt.events.MouseMoveListener() {
			public void mouseMove(org.eclipse.swt.events.MouseEvent e) {
				if(pPos==null) return;
				if(sShell.isVisible()&&
					Math.sqrt(Math.pow(pPos.x-e.x,2)+
					Math.pow(pPos.y-e.y,2))>30)
						checkVisibleAndClose();
			}
		});
    	// MouseHover: Verharren öffnet Fenster
    	styText.addMouseTrackListener(new org.eclipse.swt.events.MouseTrackAdapter() {
			public void mouseHover(org.eclipse.swt.events.MouseEvent e) {
				StyledText styledText=(StyledText)e.widget;
				// Überfahrene Zeile holen
				int line;
				try{
					line=styledText.getLineAtOffset(styledText.getOffsetAtLocation(new Point(e.x,e.y)));
				}catch(Exception ex){
					// An der betreffenden Stelle is nix
					checkVisibleAndClose();
					return;
				}
				// Text, der in dieser Zeile steht, holen
				int end, start=styledText.getOffsetAtLine(line);
				if(line==styledText.getLineCount()-1)
					end=styledText.getCharCount();
				else
					end=styledText.getOffsetAtLine(line+1)-1;
				String txt="";
				try{
					txt=styledText.getText(start,end).trim().toLowerCase();
				}catch(Exception ex){
					return;
				}
				
				// Kommando herausfilern
				int i;
				if(txt.startsWith("//")||(i=txt.indexOf("("))==-1){
					// kein Kommando
					checkVisibleAndClose();
					return;	
				}
				txt=txt.substring(0,i);
				
				// Datei suchen
				File f = new File(PathHelp.specDirTooltipSep()+txt+".htm");
				if(!f.exists()){
					// Hilfedatei nicht vorhanden
					checkVisibleAndClose();
					return;
				}
				// Datei setzen
				browser.setUrl(f.getAbsolutePath());
				
				// Anzeigen
				pPos=new Point(e.x,e.y);
				setHoverLocation(styledText.toDisplay(pPos));
				sShell.setVisible(true);
				strLine=line;
			}
		});
    	
    }
    
	/* ##########################################################################
	 * 						HILFSMETHODEN
	 * ##########################################################################*/
    
    /**
     * Berechnet die Position des Shells und setzt sie sogleich
     */
    private void setHoverLocation(Point position) {
      Rectangle displayBounds = sShell.getDisplay().getBounds();
      Rectangle shellBounds = sShell.getBounds();
      shellBounds.x = Math.max(Math.min(position.x, displayBounds.width
          - shellBounds.width), 0);
      shellBounds.y = Math.max(Math.min(position.y + 16,
          displayBounds.height - shellBounds.height), 0);
      sShell.setBounds(shellBounds);
    }
    
    /**
     * Schaut, ob das Fenster offen ist und schließt es gegebenenfalls
     */
    private void checkVisibleAndClose(){
    	if(sShell.isVisible()){
    		sShell.setVisible(false);
    		// Leere Seite setzen, damit es das nächste Mal nicht flackert
			File f = new File(PathHelp.specDirTooltipSep()+"blank.htm");
			if(f.exists()) browser.setUrl(f.getAbsolutePath());
    	}
    }
    
}
