package org.eclipse.jem.internal.proxy.remote;
/*******************************************************************************
 * Copyright (c)  2001, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
/*
 *  $RCSfile: DebugModeHelper.java,v $
 *  $Revision: 1.1 $  $Date: 2003/10/27 17:22:23 $ 
 */

import java.lang.reflect.*;

import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.jem.internal.proxy.core.ProxyPlugin;
/**
 * This is a helper for debug mode. It allows access to
 * the workbench, if available, or AWT, if available, for
 * the debug prompts. It uses reflection so that nothing is
 * forced to be loaded or pre-reqd. That way it can run headless.
 */

class DebugModeHelper {
	boolean awt = false;
	boolean console = false;
	boolean setup = false;
	java.io.InputStreamReader inReader = null;
	
	// Workbench reflections
	Object display = null;	
	Constructor cMB = null;
	Field fAppModel = null;
	Method fasync = null;
	Method fsync = null;	
	Method fSetText = null;
	Method fSetMessage = null;
	Method fOpen = null;
	Method fGetWorkbench = null;
	Class cSWT = null;
		
	
	// AWT Reflections
	Class cMessageDialog = null;
	Method fDoit = null;
	
	protected void setupType() {
		if (setup)
			return;
			
		setup = true;
		
		// See if use system console instead. If false or not set, then try to query usage.	 		
	 	console = "true".equalsIgnoreCase(Platform.getDebugOption(ProxyPlugin.getPlugin().getDescriptor().getUniqueIdentifier()+ProxyRemoteUtil.IO_CONSOLE)); //$NON-NLS-1$
	 	if (console)
	 		return;
		
		try {		 		
		 	// See if PlatformUI plugin available.
		 	Plugin uiPlugin = Platform.getPlugin("org.eclipse.ui"); //$NON-NLS-1$
		 	if (uiPlugin == null) {
		 		setupAWT();	// UI not available, try through AWT.
		 		return;
		 	}
	
	 		// Setup Eclipse
		 	Class cPlatformUI = uiPlugin.getDescriptor().getPluginClassLoader().loadClass("org.eclipse.ui.PlatformUI"); //$NON-NLS-1$
		 	fGetWorkbench = cPlatformUI.getMethod("getWorkbench", null); //$NON-NLS-1$
		 	Object w = fGetWorkbench.invoke(null, null);

			if (w != null) {
	 			Class cDisplay = uiPlugin.getDescriptor().getPluginClassLoader().loadClass("org.eclipse.swt.widgets.Display"); //$NON-NLS-1$
	 			Method fGetCurrent = cDisplay.getMethod("getCurrent", null); //$NON-NLS-1$
	 			Method fGetDefault = cDisplay.getMethod("getDefault", null);	 			 //$NON-NLS-1$
	 			fasync = cDisplay.getMethod("asyncExec", new Class[] {Runnable.class}); //$NON-NLS-1$
	 			fsync = cDisplay.getMethod("syncExec", new Class[] {Runnable.class}); //$NON-NLS-1$
	 			
	 			// Get the display
	 			display = fGetCurrent.invoke(null, null);
	 			if (display == null)
	 				display = fGetDefault.invoke(null, null);
			}
			
			if (display != null) { 	
	 			Class cShell = uiPlugin.getDescriptor().getPluginClassLoader().loadClass("org.eclipse.swt.widgets.Shell"); //$NON-NLS-1$
	 			Class cMessageBox = uiPlugin.getDescriptor().getPluginClassLoader().loadClass("org.eclipse.swt.widgets.MessageBox"); //$NON-NLS-1$
	 			cMB = cMessageBox.getConstructor(new Class[] {cShell, Integer.TYPE});

				fSetText = cMessageBox.getMethod("setText", new Class[] {String.class}); //$NON-NLS-1$
				fSetMessage = cMessageBox.getMethod("setMessage", new Class[] {String.class});				 //$NON-NLS-1$
				fOpen = cMessageBox.getMethod("open", null);		 		 //$NON-NLS-1$				
		 			
	 			cSWT = uiPlugin.getDescriptor().getPluginClassLoader().loadClass("org.eclipse.swt.SWT"); //$NON-NLS-1$
	 			fAppModel = cSWT.getField("APPLICATION_MODAL"); //$NON-NLS-1$
		 	} else {
		 		setupAWT();	// UI not available, try through AWT.
		 	}
		} catch (NoSuchMethodException e) {
		} catch (ClassNotFoundException e) {
		} catch (IllegalAccessException e) {
		} catch (InvocationTargetException e) {
		} catch (NoSuchFieldException e) {
		}
		
		return;		 			 		
		 			
	}	

	protected void setupAWT() {
	 		
	 	// See if AWT is available.
	 	try {
		 	cMessageDialog = Class.forName("org.eclipse.jem.internal.proxy.remote.MessageDialog"); //$NON-NLS-1$
		 	fDoit = cMessageDialog.getMethod("doit", new Class[] {String.class, String.class, String.class, String.class}); //$NON-NLS-1$
		 	awt = true;
		 	return;
	 	} catch (ClassNotFoundException e) {
	 	} catch (NoSuchMethodException e) {
	 	}
 		console = true;	// No AWT either, i.e. true headless environment
	} 	
	
	public boolean debugMode(final String name) {
	 	boolean debugMode = "true".equalsIgnoreCase(Platform.getDebugOption(ProxyPlugin.getPlugin().getDescriptor().getUniqueIdentifier()+ProxyRemoteUtil.DEBUG_VM)); //$NON-NLS-1$
	 	if (!debugMode)
	 		return debugMode;
	 		
	 	setupType();

		// See if use system console instead. If false or not set, then try to query usage.	 		
	 	if (console)
	 		return debugModeConsole(name);
	 		
	 	if (awt)
	 		return debugModeAWT(name);
		
		try {		 		
 			final Field fYes = cSWT.getField("YES"); //$NON-NLS-1$
 			Field fNo = cSWT.getField("NO"); //$NON-NLS-1$
 			Field fIcon = cSWT.getField("ICON_QUESTION"); //$NON-NLS-1$
	 			
 			final int style = fYes.getInt(null) | fNo.getInt(null) | fIcon.getInt(null) | fAppModel.getInt(null);	 			
 			final boolean[] db = new boolean[1];

			fsync.invoke(display, new Object[] { new Runnable() {
				/**
				 * @see java.lang.Runnable#run()
				 */
				public void run() {
					try {
						Object shell = getActiveShell();
						Object mb = cMB.newInstance(new Object[] {shell, new Integer(style)});					
						fSetText.invoke(mb, new Object[] {"Debug RemoteVM?"}); //$NON-NLS-1$
						fSetMessage.invoke(mb, new Object[] {"Do you want to start the remote vm ("+name+") in debug mode?"});	// Not NLS'd because this is for internal developers only //$NON-NLS-1$ //$NON-NLS-2$
							
						db[0] = fYes.get(null).equals(fOpen.invoke(mb, null));
					} catch (InstantiationException e) {
					} catch (IllegalAccessException e) {
					} catch (InvocationTargetException e) {
					}
				}
			}});
		 	return db[0];
		} catch (IllegalAccessException e) {
		} catch (InvocationTargetException e) {
		} catch (NoSuchFieldException e) {
		}
		
		return debugModeAWT(name);
 	}
 	

	/*
	 * This must be called from within the display thread.
	 */
	protected Object getActiveShell() {
	 	Object shell = null;		
		try {
			Object w = fGetWorkbench.invoke(null, null);
			Object ww = null;
			if (w != null) {
			 	Class cWorkbench = w.getClass();
			 	Method getWorkbenchWindow = cWorkbench.getMethod("getActiveWorkbenchWindow", null); //$NON-NLS-1$
				ww = getWorkbenchWindow.invoke(w, null);
			}
			if (ww != null) {
				Class cWorkbenchWindow = ww.getClass();
				Method getShell = cWorkbenchWindow.getMethod("getShell", null); //$NON-NLS-1$
				shell = getShell.invoke(ww, null);
			}
		} catch (IllegalAccessException e) {
		} catch (InvocationTargetException e) {
		} catch (NoSuchMethodException e) {
		}
	 	
	 	return shell;
	}	
		 	
	protected boolean debugModeAWT(String name) {
	 		
	 	// See if AWT is available.
	 	try {
		 	Integer r = (Integer) fDoit.invoke(null, new Object[] {"Debug RemoteVM?", "Do you want to start the remote vm ("+name+") in debug mode?", "Yes", "No"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
		 	return r.intValue() == 1;	// i.e. button1 or "yes" was hit.
	 	} catch (IllegalAccessException e) {
	 	} catch (InvocationTargetException e) {
	 	}
	 	
 		return false;	// No AWT either, i.e. headless environment, shouldn't of gotton here.
	} 	
	
	protected boolean debugModeConsole(String name) {
	 		
	 	// Debug through the console
 		inReader = new java.io.InputStreamReader(System.in);
 		System.out.println("Do you want to start the remote vm ("+name+") in debug mode? (Enter Y or N):"); //$NON-NLS-1$ //$NON-NLS-2$
 		char r = ' ';
 		try {
 			r = Character.toLowerCase((char) inReader.read());
 			// Need to flush the input reader now.
 			while (inReader.ready())
 				inReader.read();
		 	return r == 'y';	// i.e. "y" was entered.	 			
 		} catch (java.io.IOException e) {
 		}
	 	
 		return false;	// Error reading, so no debugging.
	} 
 	
 	/**
 	 * Return true if continue debugging.
 	 */
	public boolean promptPort(final int dport) {
 		if (awt)
 			return promptPortAWT(dport);
 		else if (console)
 			return promptPortConsole(dport);
 			
 		try {	
			final Field fOK = cSWT.getField("OK"); //$NON-NLS-1$
			Field fCancel = cSWT.getField("CANCEL"); //$NON-NLS-1$
			Field fIcon = cSWT.getField("ICON_WORKING"); //$NON-NLS-1$
	 			
			final int style = fOK.getInt(null) | fCancel.getInt(null) | fIcon.getInt(null) | fAppModel.getInt(null);

			final boolean[] ok = new boolean[1];
			fsync.invoke(display, new Object[] { new Runnable() {	
				/**
				 * @see java.lang.Runnable#run()
				 */
				public void run() {
					try {
						Object shell = getActiveShell();
						Object mb = cMB.newInstance(new Object[] {shell, new Integer(style)});					
						fSetText.invoke(mb, new Object[] {"Connect Debugger to RemoteVM!"}); //$NON-NLS-1$
						fSetMessage.invoke(mb, new Object[] {"You must now attach the debugger to port number "+dport+". Press OK when the debugger is attached. The program will not continue properly without the debugger being attached. Press Cancel if you could not connect the debugger. This will still cause an error, but it will clean up better."});	// Not NLS'd because this is for internal developers only //$NON-NLS-1$ //$NON-NLS-2$
						ok[0] = fOK.get(null).equals(fOpen.invoke(mb, null));
					} catch (InstantiationException e) {
					} catch (IllegalAccessException e) {
					} catch (InvocationTargetException e) {
					}
				}
			}});			
			return ok[0];
 		} catch (NoSuchFieldException e) {
 		} catch (InvocationTargetException e) {
 		} catch (IllegalAccessException e) {
 		}
 		return false;
	}	 	
 	
	protected boolean promptPortAWT(int dport) {
		try {
		 	Integer r = (Integer) fDoit.invoke(null, new Object[] {"Connect Debugger to RemoteVM!", "You must now attach the debugger to port number "+dport+". Press OK when the debugger is attached. The program will not continue properly without the debugger being attached. Press Cancel if you could not connect the debugger. This will still cause an error, but it will clean up better.", "OK", "Cancel"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
		 	return r.intValue() == 1;	// i.e. button1 or "OK" was hit.
		} catch (InvocationTargetException e) {
		} catch (IllegalAccessException e) {
		}
 		
		return false;
	}
		 	
 	protected boolean promptPortConsole(int dport) {
		System.out.println("You must now attach the debugger to port number "+dport+". Enter 'y' when the debugger is attached. The program will not continue properly without the debugger being attached. Press 'n' if you could not connect the debugger. This will still cause an error, but it will clean up better. Enter 'y' or 'n':"); //$NON-NLS-1$ //$NON-NLS-2$
		char r = ' ';
		try {
			r = Character.toLowerCase((char) inReader.read());
 			while (inReader.ready())
 				inReader.read();
			return r == 'y';	// i.e. "y" was entered, go on
		} catch (java.io.IOException e) {
		}
 		
		return false;
	}
	
	/**
	 * Display an error msg. There will only be an OK button.
	 * This will always display, debug mode won't be looked at.
	 * This is for errors. This will be displayed async, so this
	 * may return before the msg has been displayed and answered,
	 * but since the only response is OK, it doesn't really matter.
	 */
	public void displayErrorMessage(final String title, final String msg) {
		setupType();
		if (console)
			displayErrorMessageConsole(title, msg);
		else if (awt)
			displayErrorMessageAWT(title, msg);
			
 		try {
 			// This needs to be done in display thread.	
			Field fOK = cSWT.getField("OK"); //$NON-NLS-1$
			Field fIcon = cSWT.getField("ICON_ERROR"); //$NON-NLS-1$
	 			
			final int style = fOK.getInt(null) | fIcon.getInt(null) | fAppModel.getInt(null);
			fasync.invoke(display, new Object[] { new Runnable() {	
				/**
				 * @see java.lang.Runnable#run()
				 */
				public void run() {			
					try {
						Object shell = getActiveShell();
						Object mb = cMB.newInstance(new Object[] {shell, new Integer(style)});
						
						fSetText.invoke(mb, new Object[] {title});
						fSetMessage.invoke(mb, new Object[] {msg});
						fOpen.invoke(mb, null);
					} catch (InstantiationException e) {
					} catch (IllegalAccessException e) {
					} catch (InvocationTargetException e) {
					}
				}
			}});
 		} catch (NoSuchFieldException e) {
 		} catch (InvocationTargetException e) {
 		} catch (IllegalAccessException e) {
 		}		
	}	
	
 	protected void displayErrorMessageConsole(String title, String msg) {
		System.out.println("Error: " + title); //$NON-NLS-1$
		System.out.println("       " + msg); //$NON-NLS-1$
	}
	
	protected void displayErrorMessageAWT(String title, String msg) {
		try {
		 	fDoit.invoke(null, new Object[] {title, msg, ProxyRemoteMessages.getString("OK_7"), null}); //$NON-NLS-1$
		} catch (InvocationTargetException e) {
		} catch (IllegalAccessException e) {
		}
	}		
}