/*******************************************************************************
 * Copyright (c) 2003, 2007 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.osgi.framework.internal.core;

import java.io.*;
import java.lang.reflect.*;
import java.net.URL;
import java.util.*;
import org.eclipse.osgi.framework.console.CommandInterpreter;
import org.eclipse.osgi.framework.console.CommandProvider;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Bundle;

/**
 * This class knows how to parse and execute the command line arguments to the FrameworkConsole.
 * It attempts to pass the command to each registered CommandProvider until it finds one
 * that knows what to do with it.
 *
 * FrameworkCommandInterpreter provides support for the "More" command which allows the operator to configure
 * the number of lines to display before being prompted to continue.
 *
 * FrameworkCommandInterpreter provides several print methods which handle the "More" command.
 */
public class FrameworkCommandInterpreter implements CommandInterpreter {
	private static final String WS_DELIM = " \t\n\r\f"; //$NON-NLS-1$

	/** The command line in StringTokenizer form */
	private StringTokenizer tok;
	/** The active CommandProviders */
	private Object[] commandProviders;
	/** The FrameworkConsole */
	private FrameworkConsole con;
	/** The stream to send output to */
	private PrintWriter out;

	/** Strings used to format other strings */
	private String tab = "\t"; //$NON-NLS-1$
	private String newline = "\r\n"; //$NON-NLS-1$
	private boolean firstCommand = true;

	/**
	 * The maximum number of lines to print without user prompt.
	 * 0 means no user prompt is required, the window is scrollable.
	 */
	protected static int maxLineCount;

	/** The number of lines printed without user prompt.*/
	protected int currentLineCount;

	/**
	 *  The constructor.  It turns the cmdline string into a StringTokenizer and remembers
	 *  the input parms.
	 */
	public FrameworkCommandInterpreter(String cmdline, Object[] commandProviders, FrameworkConsole con) {
		tok = new StringTokenizer(cmdline);
		this.commandProviders = commandProviders;
		this.con = con;
		this.out = con.getWriter();
	}

	/**
	 Get the next argument in the input.
	 
	 E.g. if the commandline is hello world, the _hello method
	 will get "world" as the first argument.
	 
	 @return A string containing the next argument on the command line
	 */
	public String nextArgument() {
		if (tok == null || !tok.hasMoreElements())
			return null;
		
		String arg = tok.nextToken();
		if (arg.startsWith("\"")) { //$NON-NLS-1$
			if (arg.endsWith("\"")) { //$NON-NLS-1$
				if (arg.length() >= 2)
					// strip the beginning and ending quotes
					return arg.substring(1, arg.length() - 1);
			}
			String remainingArg = tok.nextToken("\""); //$NON-NLS-1$
			arg = arg.substring(1) + remainingArg;
			// skip to next whitespace separated token
			tok.nextToken(WS_DELIM);
		} else if (arg.startsWith("'")) { //$NON-NLS-1$ //$NON-NLS-2$
			if (arg.endsWith("'")) { //$NON-NLS-1$
				if (arg.length() >= 2)
					// strip the beginning and ending quotes
					return arg.substring(1, arg.length() - 1);
			}
			String remainingArg = tok.nextToken("'"); //$NON-NLS-1$
			arg = arg.substring(1) + remainingArg;
			// skip to next whitespace separated token
			tok.nextToken(WS_DELIM);
		}
		return arg;
	}

	/**
	 Execute a command line as if it came from the end user.
	 
	 Searches the list of command providers using introspection until
	 it finds one that contains a matching method.  It searches for a method
	 with the name "_cmd" where cmd is the command to execute.  For example,
	 for a command of "launch" execute searches for a method called "_launch".
	 
	 @param cmd The name of the command to execute.
	 @return The object returned by the method executed.
	 */
	public Object execute(String cmd) {
		if (!firstCommand)
			return innerExecute(cmd);
		firstCommand = false;
		resetLineCount();
		Object retval = null;
		// handle "more" command here
		if (cmd.equalsIgnoreCase("more")) { //$NON-NLS-1$
			try {
				_more();
			} catch (Exception e) {
				printStackTrace(e);
			}
			return retval;
		}
		// handle "disconnect" command here
		if (cmd.equalsIgnoreCase("disconnect") && con.getUseSocketStream()) { //$NON-NLS-1$
			try {
				_disconnect();
			} catch (Exception e) {
				printStackTrace(e);
			}
			return retval;
		}
		Class[] parameterTypes = new Class[] {CommandInterpreter.class};
		Object[] parameters = new Object[] {this};
		boolean executed = false;
		int size = commandProviders.length;
		for (int i = 0; !executed && (i < size); i++) {
			try {
				Object target = commandProviders[i];
				Method method = target.getClass().getMethod("_" + cmd, parameterTypes); //$NON-NLS-1$
				retval = method.invoke(target, parameters);
				executed = true; // stop after the command has been found
			} catch (NoSuchMethodException ite) {
				// keep going - maybe another command provider will be able to execute this command
			} catch (InvocationTargetException ite) {
				executed = true; // don't want to keep trying - we found the method but got an error
				printStackTrace(ite.getTargetException());
			} catch (Exception ee) {
				executed = true; // don't want to keep trying - we got an error we don't understand
				printStackTrace(ee);
			}
		}
		// if no command was found to execute, display help for all registered command providers
		if (!executed) {
			for (int i = 0; i < size; i++) {
				try {
					CommandProvider commandProvider = (CommandProvider) commandProviders[i];
					out.print(commandProvider.getHelp());
					out.flush();
				} catch (Exception ee) {
					printStackTrace(ee);
				}
			}
			// call help for the more command provided by this class
			out.print(getHelp());
			out.flush();
		}
		return retval;
	}

	private Object innerExecute(String cmd) {
		if (cmd != null && cmd.length() > 0) {
			CommandInterpreter intcp = new FrameworkCommandInterpreter(cmd, commandProviders, con);
			String command = intcp.nextArgument();
			if (command != null)
				return intcp.execute(command);
		}
		return null;
	}

	/**
	 * Answers the number of lines output to the console
	 * window should scroll without user interaction.
	 *
	 * @return	The number of lines to scroll.
	 */
	private int getMaximumLinesToScroll() {
		return maxLineCount;
	}

	/**
	 * Sets the number of lines output to the console
	 * window will scroll without user interaction.
	 * <p>
	 * Note that this number does not include the line
	 * for the 'more' prompt itself.
	 * <p>
	 * If the number of lines is 0 then no 'more' prompt
	 * is disabled.
	 *
	 * @param	lines	the number of lines to scroll
	 */
	private void setMaximumLinesToScroll(int lines) {
		if (lines < 0) {
			throw new IllegalArgumentException(ConsoleMsg.CONSOLE_LINES_TO_SCROLL_NEGATIVE_ERROR); 
		}

		maxLineCount = lines;
	}

	/**
	 * Resets the line counter for the 'more' prompt.
	 */
	private void resetLineCount() {
		currentLineCount = 0;
	}

	/**
	 * Prints a string to the output medium (appended with newline character).
	 * <p>
	 * This method does not increment the line counter for the 'more' prompt.
	 *
	 * @param o the string to be printed
	 */
	private void printline(Object o) {
		print(o + newline);
	}

	/**
	 * Prints an object to the outputstream
	 *
	 * @param o	the object to be printed
	 */
	public void print(Object o) {
		synchronized (out) {
			check4More();
			out.print(o);
			out.flush();
		}
	}

	/**
	 * Prints a empty line to the outputstream
	 */
	public void println() {
		println(""); //$NON-NLS-1$
	}

	/**
	 * Print a stack trace including nested exceptions.
	 * @param t The offending exception
	 */
	public void printStackTrace(Throwable t) {
		t.printStackTrace(out);

		Method[] methods = t.getClass().getMethods();

		int size = methods.length;
		Class throwable = Throwable.class;

		for (int i = 0; i < size; i++) {
			Method method = methods[i];

			if (Modifier.isPublic(method.getModifiers()) && method.getName().startsWith("get") && throwable.isAssignableFrom(method.getReturnType()) && (method.getParameterTypes().length == 0)) { //$NON-NLS-1$
				try {
					Throwable nested = (Throwable) method.invoke(t, null);

					if ((nested != null) && (nested != t)) {
						out.println(ConsoleMsg.CONSOLE_NESTED_EXCEPTION);
						printStackTrace(nested);
					}
				} catch (IllegalAccessException e) {
				} catch (InvocationTargetException e) {
				}
			}
		}
	}

	/**
	 * Prints an object to the output medium (appended with newline character).
	 * <p>
	 * If running on the target environment, the user is prompted with '--more'
	 * if more than the configured number of lines have been printed without user prompt.
	 * This enables the user of the program to have control over scrolling.
	 * <p>
	 * For this to work properly you should not embed "\n" etc. into the string.
	 *
	 * @param	o	the object to be printed
	 */
	public void println(Object o) {
		if (o == null) {
			return;
		}
		synchronized (out) {
			check4More();
			printline(o);
			currentLineCount++;
			currentLineCount += o.toString().length() / 80;
		}
	}

	/**
	 * Prints the given dictionary sorted by keys.
	 *
	 * @param dic	the dictionary to print
	 * @param title	the header to print above the key/value pairs
	 */
	public void printDictionary(Dictionary dic, String title) {
		if (dic == null)
			return;

		int count = dic.size();
		String[] keys = new String[count];
		Enumeration keysEnum = dic.keys();
		int i = 0;
		while (keysEnum.hasMoreElements()) {
			keys[i++] = (String) keysEnum.nextElement();
		}
		Util.sort(keys);

		if (title != null) {
			println(title);
		}
		for (i = 0; i < count; i++) {
			println(" " + keys[i] + " = " + dic.get(keys[i])); //$NON-NLS-1$//$NON-NLS-2$
		}
		println();
	}

	/**
	 * Prints the given bundle resource if it exists
	 *
	 * @param bundle	the bundle containing the resource
	 * @param resource	the resource to print
	 */
	public void printBundleResource(Bundle bundle, String resource) {
		URL entry = null;
		entry = bundle.getEntry(resource);
		if (entry != null) {
			try {
				println(resource);
				InputStream in = entry.openStream();
				byte[] buffer = new byte[1024];
				int read = 0;
				try {
					while ((read = in.read(buffer)) != -1)
						print(new String(buffer, 0, read));
				} finally {
					if (in != null) {
						try {
							in.close();
						} catch (IOException e) {
						}
					}
				}
			} catch (Exception e) {
				System.err.println(NLS.bind(ConsoleMsg.CONSOLE_ERROR_READING_RESOURCE, resource));
			}
		} else {
			println(NLS.bind(ConsoleMsg.CONSOLE_RESOURCE_NOT_IN_BUNDLE, resource, bundle.toString())); 
		}
	}

	/**
	 *  Displays the more... prompt if the max line count has been reached 
	 *  and waits for the operator to hit enter.
	 *
	 */
	private void check4More() {
		int max = getMaximumLinesToScroll();
		if (max > 0) {
			if (currentLineCount >= max) {
				out.print(ConsoleMsg.CONSOLE_MORE);
				out.flush();
				con.getInput(); // wait for user entry
				resetLineCount(); //Reset the line counter for the 'more' prompt
			}
		}
	}

	/**
	 Answer a string (may be as many lines as you like) with help
	 texts that explain the command.
	 */
	public String getHelp() {
		StringBuffer help = new StringBuffer(256);
		help.append(newline);
		help.append(ConsoleMsg.CONSOLE_HELP_CONTROLLING_CONSOLE_HEADING);
		help.append(newline);
		help.append(tab);
		help.append("more - "); //$NON-NLS-1$
		help.append(ConsoleMsg.CONSOLE_HELP_MORE);
		if (con.getUseSocketStream()) {
			help.append(newline);
			help.append(tab);
			help.append("disconnect - "); //$NON-NLS-1$
			help.append(ConsoleMsg.CONSOLE_HELP_DISCONNECT);
		}
		return help.toString();
	}

	/**
	 * Toggles the use of the more prompt for displayed output.
	 *
	 */
	public void _more() throws Exception {
		if (confirm(ConsoleMsg.CONSOLE_CONFIRM_MORE, true)) {
			int lines = prompt(newline + ConsoleMsg.CONSOLE_MORE_ENTER_LINES, 24);
			setMaximumLinesToScroll(lines);
		} else {
			setMaximumLinesToScroll(0);
		}
	}

	private void _disconnect() throws Exception {
		if (confirm(ConsoleMsg.CONSOLE_CONFIRM_DISCONNECT, true)) {
			con.disconnect();
		}
	}

	/**
	 * Prompts the user for confirmation.
	 *
	 * @param	string			the message to present to the user to confirm
	 * @param	defaultAnswer	the default result
	 *
	 * @return	<code>true</code> if the user confirms; <code>false</code> otherwise.
	 */
	protected boolean confirm(String string, boolean defaultAnswer) {
		synchronized (out) {
			if (string.length() > 0) {
				print(string);
			} else {
				print(ConsoleMsg.CONSOLE_CONFIRM);
			}
			print(" (" + ConsoleMsg.CONSOLE_CONFIRM_VALUES); //$NON-NLS-1$
			if (defaultAnswer) {
				print(ConsoleMsg.CONSOLE_Y + ") "); //$NON-NLS-1$
			} else {
				print(ConsoleMsg.CONSOLE_N + ") "); //$NON-NLS-1$
			}
		}
		String input = con.getInput();
		resetLineCount();
		if (input.length() == 0) {
			return defaultAnswer;
		}
		return input.toLowerCase().charAt(0) == ConsoleMsg.CONSOLE_Y.charAt(0);
	}

	/**
	 * Prompts the user for input from the input medium providing a default value.
	 *
	 * @param	string			the message to present to the user
	 * @param	defaultAnswer	the string to use as a default return value
	 *
	 * @return	The user provided string or the defaultAnswer,
	 *			if user provided string was empty.
	 */
	protected String prompt(String string, String defaultAnswer) {
		if (string.length() > 0) {
			if (defaultAnswer.length() > 0) {
				StringBuffer buf = new StringBuffer(256);
				buf.append(string);
				buf.append(" "); //$NON-NLS-1$
				buf.append(ConsoleMsg.CONSOLE_PROMPT_DEFAULT);
				buf.append("="); //$NON-NLS-1$
				buf.append(defaultAnswer);
				buf.append(") "); //$NON-NLS-1$
				print(buf.toString());
			} else {
				print(string);
			}
		}
		String input = con.getInput();
		resetLineCount();
		if (input.length() > 0) {
			return input;
		}
		return defaultAnswer;
	}

	/**
	 * Prompts the user for input of a positive integer.
	 *
	 * @param	string			the message to present to the user
	 * @param	defaultAnswer	the integer to use as a default return value
	 *
	 * @return	The user provided integer or the defaultAnswer,
	 *			if user provided an empty input.
	 */
	protected int prompt(String string, int defaultAnswer) {
		Integer i = new Integer(defaultAnswer);
		int answer;
		for (int j = 0; j < 3; j++) {
			String s = prompt(string, i.toString());
			try {
				answer = Integer.parseInt(s);
				if (answer >= 0) {
					return answer;
				}
			} catch (NumberFormatException e) {
			}
			println(ConsoleMsg.CONSOLE_INVALID_INPUT);
		}
		println(ConsoleMsg.CONSOLE_TOO_MUCH_INVALID_INPUT);
		return defaultAnswer;
	}
}
