/*******************************************************************************
 * Copyright (c) 2003, 2005 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.swt.tools.internal;
import java.io.*;
import java.util.*;

/* Produces the java classes mapping to XPCOM Mozilla objects */
public class MozillaGenerator {
	FileReader r = null;
	FileWriter w = null;
	int maxLines = 1000;
	int cntLines = 0;
	int n = 0;
	String[] b = null;
	String body = null;
	int nMethods = 0;
	String uuidName;
	String uuidValue;
	String className;
	String parentName;
	String[] constantNames;
	String[] constantValues;
	String[] methodNames;
	String[][] argTypes;
	String[][] argNames;
	String bodyOrder;
	Hashtable vtbls;

	static boolean DEBUG = false;

	// Contains the characters found before a method name
	// Useful to extract the method name. e.g.
	//  NS_IMETHOD QueryInterface(const nsIID & uuid, void * *result) = 0;
	//  NS_IMETHOD_(nsrefcnt) AddRef(void) = 0;
	// method name follows: QueryInterface, AddRef etc.
	static String[] BEFORE_METHOD_NAME = {
		"  NS_IMETHOD ",
		"  NS_IMETHOD_(nsrefcnt) ",
		"  NS_IMETHOD_(void *) ",
		"  NS_IMETHOD_(void) "
	};
	static String NO_SUPER_CLASS = "SWT_NO_SUPER_CLASS";
	
	static String[][] TYPES_C2JAVA = { 
		{ "PRBool *", "boolean[]" },
		{ "nsIID &", "nsID" },
		{ "nsCID &", "nsID" },
		{ "nsCID * *", "int /*long*/" }, // nsID[] not supported by jnigen
		{ "* *", "int /*long*/[]" },
		{ "**", "int /*long*/[]" },
		{ "* &", "int /*long*/[]" },
		{ "PRUint32 *", "int[]" }, 
		{ "PRInt32 *", "int[]" },
		{ "PRInt64 *", "long[]" },
		{ "PRUnichar *", "char[]" },
		{ "char *", "byte[]" },
		{ "float *", "float[]" },
		{ "PRUint16 *", "short[]" },
		{ "nativeWindow *", "int /*long*/[]" },
		{ "nsWriteSegmentFun", "int /*long*/" },
		{ "nativeWindow", "int /*long*/" },

		{ "*", "int /*long*/" }, // c type containing one or more * (and any other character, and did not match previous patterns) is a simple pointer
		{ "&", "int /*long*/" }, 

		{ "PRUint32", "int" },
		{ "PRInt32", "int" }, 
		{ "PRInt64", "long" }, 
		{ "nsresult", "int" },
		{ "PRBool", "boolean" },
		{ "float", "float" },
		{ "PRUint16", "short" },
		{ "size_t", "int" },
		};

	static String GECKO = "/bluebird/teamswt/swt-builddir/mozilla/1.4/linux_gtk2/mozilla/dist/include/";
	static String TARGET_FOLDER = "/bluebird/teamswt/chrisx/amd64/workspace/org.eclipse.swt/Eclipse SWT Mozilla/common/org/eclipse/swt/internal/mozilla/";
	static String[] XPCOM_HEADERS = { 
		"profile/nsIProfile.h",
		"widget/nsIAppShell.h",
		"widget/nsIBaseWindow.h", 
		"xpcom/nsIComponentManager.h",
		"xpcom/nsIComponentRegistrar.h",
		"webbrwsr/nsIContextMenuListener.h", 
		"docshell/nsIDocShell.h",
		"dom/nsIDOMEvent.h", 
		"dom/nsIDOMMouseEvent.h",
		"dom/nsIDOMUIEvent.h", 
		"dom/nsIDOMWindow.h",
		"uriloader/nsIDownload.h", 
		"webbrwsr/nsIEmbeddingSiteWindow.h",
		"xpcom/nsIFactory.h", 
		"xpcom/nsIFile.h",
		"helperAppDlg/nsIHelperAppLauncherDialog.h",
		"exthandler/nsIExternalHelperAppService.h", // contains nsIHelperAppLauncher
		"xpcom/nsIInputStream.h", 
		"xpcom/nsIInterfaceRequestor.h",
		"necko/nsIIOService.h", 
		"xpcom/nsILocalFile.h", 
		"xpcom/nsIMemory.h",
		"progressDlg/nsIProgressDialog.h",
		"windowwatcher/nsIPromptService.h", 
		"xpcom/nsIServiceManager.h",
		"xpcom/nsISupports.h", 
		"webbrwsr/nsITooltipListener.h", 
		"necko/nsIURI.h",
		"uriloader/nsIURIContentListener.h", 
		"xpcom/nsIWeakReference.h",
		"webbrwsr/nsIWebBrowser.h", 
		"webbrwsr/nsIWebBrowserChrome.h",
		"webbrwsr/nsIWebBrowserChromeFocus.h",
		"webbrwsr/nsIWebBrowserFocus.h", 
		"docshell/nsIWebNavigation.h",
		"uriloader/nsIWebProgress.h", 
		"uriloader/nsIWebProgressListener.h",
		"embed_base/nsIWindowCreator.h", 
		"windowwatcher/nsIWindowWatcher.h" };

	public static void main(String[] args) {
		MozillaGenerator x = new MozillaGenerator();
		for (int i = 0; i < XPCOM_HEADERS.length; i++)
			x.parse(GECKO + XPCOM_HEADERS[i], TARGET_FOLDER);
		x.outputVtblCall();
		System.out.println("done");
	}

	public MozillaGenerator() {
		vtbls = new Hashtable();
	}

	/** Write callbacks */
	public void write(String data) {
		if (DEBUG) {
			System.out.print(data);
			return;
		}
		try {
			w.write(data);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void writeLine() {
		if (DEBUG) {
			System.out.println();
			return;
		}
		write("\r\n");
	}

	public void writeLine(String data) {
		if (DEBUG) {
			System.out.println(data);
			return;
		}
		write(data + "\r\n");
	}

	public void writeCopyrights() {
		writeLine(COPYRIGHTS);
	}

	public void writePackageDeclaration() {
		writeLine(PACKAGE_DECLARATION);
	}

	public void writeClassDeclaration(String className, String parentName) {
		String line = "public class " + className;
		if (!parentName.equals(NO_SUPER_CLASS)) line += " extends " + parentName;
		line += " {";
		writeLine(line);
	}

	public void writeLastMethodId(String parentName, int nMethods) {
		String line = "\tstatic final int LAST_METHOD_ID = ";
		if (!parentName.equals(NO_SUPER_CLASS)) line += parentName + ".LAST_METHOD_ID + " + nMethods + ";";
		else line += "" + (nMethods - 1)+ ";"; // zero indexed
		writeLine(line);
	}

	public void writeIID(String uuidName, String uuidValue) {
		writeLine("\tpublic static final String " + uuidName + " =");
		writeLine("\t\t\"" + uuidValue + "\";");
		writeLine();
		String iid = uuidName.substring(0, uuidName.indexOf("_STR"));
		writeLine("\tpublic static final nsID " + iid + " =");
		writeLine("\t\tnew nsID(" + uuidName + ");");
	}

	public void writeAddressField() {
		writeLine("\tint /*long*/ address;");
	}
	public void writeConstructor(String className, String parentName) {
		writeLine("\tpublic " + className + "(int /*long*/ address) {");
		if (!parentName.equals(NO_SUPER_CLASS)) {
			writeLine("\t\tsuper(address);");
		} else {
			writeLine("\t\tthis.address = address;");
		}
		writeLine("\t}");
	}

	public void writeAddressGetter() {
		writeLine("\tpublic int /*long*/ getAddress() {");
		writeLine("\t\treturn this.address;");
		writeLine("\t}");
	}
	
	public void writeConstant(String name, String value) {
		writeLine("\tpublic static final int " + name + " = " + value + ";");
	}

	public void writeMethod(String name, String parentName, int methodIndex, String[] argTypes, String[] argNames) {
		write("\tpublic int " + name + "(");
		for (int i = 0; i < argTypes.length; i++) {
			write(argTypes[i] + " " + argNames[i]);
			if (i < argTypes.length - 1)
				write(", ");
		}
		write(") {");
		writeLine();
		String line = "\t\treturn XPCOM.VtblCall(";
		if (!parentName.equals(NO_SUPER_CLASS)) line += parentName + ".LAST_METHOD_ID + " + (methodIndex + 1) + ", getAddress()";
		else line += methodIndex + ", getAddress()"; // zero indexed
		write(line);
		if (argTypes.length > 0)
			write(", ");
		for (int i = 0; i < argTypes.length; i++) {
			write(argNames[i]);
			if (i < argTypes.length - 1)
				write(", ");
		}
		writeLine(");");
		writeLine("\t}");
	}

	public void writeClassEnd() {
		write("}");
	}

	public void logVtblCall(String[] argTypes) {
		String vtbl = "static final native int VtblCall(int fnNumber, int /*long*/ ppVtbl";
		if (argTypes.length > 0)
			vtbl += ", ";
		for (int i = 0; i < argTypes.length; i++) {
			vtbl += argTypes[i] + " arg" + i;
			if (i < argTypes.length - 1)
				vtbl += ", ";
		}
		vtbl += ");";
		Integer key = new Integer(argTypes.length);
		Vector list = (Vector) vtbls.get(key);
		if (list == null) {
			list = new Vector();
			vtbls.put(key, list);
		}
		boolean duplicate = false;
		Enumeration e = list.elements();
		while (e.hasMoreElements()) {
			String s = (String) e.nextElement();
			if (vtbl.equals(s)) {
				duplicate = true;
				break;
			}
		}
		if (!duplicate)
			list.add(vtbl);
	}

	public void outputVtblCall() {
		Enumeration e = vtbls.keys();
		int n = 0;
		while (e.hasMoreElements()) {
			e.nextElement();
			n++;
		}
		Integer[] keys = new Integer[n];
		e = vtbls.keys();
		n = 0;
		while (e.hasMoreElements()) {
			keys[n] = (Integer) e.nextElement();
			n++;
		}
		Arrays.sort(keys);
		for (int i = 0; i < keys.length; i++) {
			Vector list = (Vector) vtbls.get(keys[i]);
			Object[] elts = (Object[]) list.toArray();
			Arrays.sort(elts);
			for (int j = 0; j < elts.length; j++) {
				System.out.println(elts[j]);
			}
		}

	}

	/** Parsing invoking write callbacks */

	/*
	 * Convert a C header file into a Java source file matching SWT Mozilla
	 binding.
	 */
	public void parse(String src, String destPath) {
		if (DEBUG) writeLine("*** PARSING <"+src+"> to folder "+destPath);
		b = new String[maxLines];
		cntLines = 0;
		try {
			r = new FileReader(src);
			BufferedReader br = new BufferedReader(r);
			while ((b[cntLines] = br.readLine()) != null) {
				cntLines++;
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
			return;
		}
		n = 0;
		boolean lookForClasses = true;
		while (lookForClasses) {	
			/* parsing */
			lookForClasses = parse();
	
			String destFile = destPath + className + ".java";
			try {
				w = new FileWriter(destFile);
				if (DEBUG) writeLine("** CREATED JAVA FILE <"+destFile+">");
			} catch (IOException e) {
				e.printStackTrace();
				return;
			}
	
			/* writing */
			writeCopyrights();
			writePackageDeclaration();
			writeLine();
			writeClassDeclaration(className, parentName);
			writeLine();
			writeLastMethodId(parentName, nMethods);
			writeLine();
			writeIID(uuidName, uuidValue);
			writeLine();
			if (parentName.equals(NO_SUPER_CLASS)) {
				writeAddressField();
				writeLine();
			}
			writeConstructor(className, parentName);
			writeLine();
			
			if (parentName.equals(NO_SUPER_CLASS)) {
				writeAddressGetter();
				writeLine();
			}
	
			int constantIndex = 0, methodIndex = 0;
			for (int i = 0; i < bodyOrder.length(); i++) {
				if (bodyOrder.charAt(i) == 'C') {
					writeConstant(constantNames[constantIndex],
							constantValues[constantIndex]);
					if (i < bodyOrder.length() - 1) writeLine();
					constantIndex++;
				} else if (bodyOrder.charAt(i) == 'M') {
					writeMethod(methodNames[methodIndex], parentName, methodIndex,
							argTypes[methodIndex], argNames[methodIndex]);
					if (i < bodyOrder.length() - 1) writeLine();
					methodIndex++;
				}
			}
	
			writeClassEnd();
	
			try {
				w.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public String getPackages() {
		return "package org.eclipse.swt.internal.mozilla;";
	}

	public boolean parse() {
		if (!jumpToUuidDeclaration()) return false;
		uuidName = getUuidName(b[n]);
		if (DEBUG)
			System.out.println("UUID name: <" + uuidName + ">");
		uuidValue = getUuidValue(b[n]);
		if (DEBUG)
			System.out.println("UUID value: <" + uuidValue + ">");
		jumpToInterfaceDeclaration();
		className = getClassName(b[n]);
		if (DEBUG)
			System.out.println("Interface name: <" + className + ">");
		parentName = getParentName(b[n]);
		if (DEBUG)
			System.out.println("parentName: <" + parentName + ">");
		parseBody();
		return true;
	}

	boolean jumpToUuidDeclaration() {
		// jump to line matching: "#define NS_IWEBBROWSERCHROME_IID_STR "ba434c60-9d52-11d3-afb0-00a024ffc08c""
		while (!(b[n].startsWith("#define ") && b[n].indexOf("_IID_STR \"") != -1)) {
			n++;
			if (n >= cntLines) return false;
		}
		return true;
	}

	//assume a declaration matching: "#define NS_IWEBBROWSERCHROME_IID_STR "ba434c60-9d52-11d3-afb0-00a024ffc08c""
	//returns NS_IWEBBROWSERCHROME_IID_STR
	String getUuidName(String declaration) {
		return declaration.substring(declaration.indexOf("#define ")
				+ "#define ".length(), declaration.indexOf(" \""));
	}

	//assume a declaration matching: "#define NS_IWEBBROWSERCHROME_IID_STR "ba434c60-9d52-11d3-afb0-00a024ffc08c""
	//returns ba434c60-9d52-11d3-afb0-00a024ffc08c
	String getUuidValue(String declaration) {
		return declaration.substring(declaration.indexOf("_IID_STR \"")
				+ "_IID_STR \"".length(), declaration.lastIndexOf('"'));
	}

	void jumpToInterfaceDeclaration() {
		// jump to line matching: "class NS_NO_VTABLE nsIWebBrowserChrome : public nsISupports {"
		while (!(b[n].startsWith("class NS_NO_VTABLE "))) {
			n++;
		}
	}

	// assume a declaration matching: "class NS_NO_VTABLE nsIWebBrowserChrome : public nsISupports {"
	// returns nsIWebBrowserChrome
	// special case for nsISupports that has no super class: class NS_NO_VTABLE nsISupports {
	String getClassName(String declaration) {
		int endIndex = declaration.indexOf(" :");
		// nsISupports special case (no super class)
		if (endIndex == -1) endIndex = declaration.indexOf(" {");
		return declaration.substring(declaration.indexOf("class NS_NO_VTABLE ")
				+ "class NS_NO_VTABLE ".length(), endIndex);
	}

	// assume a declaration matching: "class NS_NO_VTABLE nsIWebBrowserChrome : public nsISupports {"
	// returns nsISupports
	// special case for nsISupports that has no super class: class NS_NO_VTABLE nsISupports {
	String getParentName(String declaration) {
		if (declaration.indexOf(" :") == -1) return NO_SUPER_CLASS;
		return declaration.substring(declaration.indexOf(": public ")
				+ ": public ".length(), declaration.indexOf(" {"));
	}

	// parse methods and constants declarations starting at the current index
	// out:
	// .String body - contains the corresponding java content
	// .n - set to the end of the interface body declaration ( line with the enclosing "};" )
	// .nMethods    - set to the number of methods parsed
	void parseBody() {
		body = "";
		bodyOrder = "";
		int nConstants = 0;
		nMethods = 0;

		int tmp_n = n;
		while (true) {
			int type = jumpToNextConstantOrMethod();
			if (type == CONSTANT)
				nConstants++;
			if (type == METHOD)
				nMethods++;
			if (type == END_BODY)
				break;
			n++;
		}
		n = tmp_n;
		constantNames = new String[nConstants];
		constantValues = new String[nConstants];
		methodNames = new String[nMethods];
		argTypes = new String[nMethods][];
		argNames = new String[nMethods][];
		int constantIndex = 0, methodIndex = 0;
		while (true) {
			int type = jumpToNextConstantOrMethod();
			if (type == CONSTANT) {
				parseConstant(b[n], constantIndex);
				bodyOrder += "C";
				constantIndex++;
			}
			if (type == METHOD) {
				parseMethod(b[n], methodIndex);
				logVtblCall(argTypes[methodIndex]);
				bodyOrder += "M";
				methodIndex++;
			}
			if (type == END_BODY)
				return;
			n++;
		}
	}

	static int CONSTANT = 0;

	static int METHOD = 1;

	static int END_BODY = 2;

	boolean isEndOfInterfaceBody() {
		return b[n].startsWith("};");
	}

	int jumpToNextConstantOrMethod() {
		while (!isEndOfInterfaceBody()) {
			if (b[n].startsWith("  enum { ")) {
				return CONSTANT;
			}
			if (methodNameStartIndexOf(b[n]) != -1) {
				return METHOD;
			}
			n++;
		}
		return END_BODY;
	}

	void parseConstant(String constant, int constantIndex) {
		String constantName = constant.substring(constant.indexOf(" enum { ")
				+ " enum { ".length(), constant.indexOf(" ="));
		if (DEBUG)
			writeLine("constantName <" + constantName + ">");
		constantNames[constantIndex] = constantName;
		
		// most constants values have a trailing U
		// enum { APP_TYPE_UNKNOWN = 0U };
		int endIndex = constant.indexOf("U };");
		// a few others don't
		// enum { ENUMERATE_FORWARDS = 0 };		
		if (endIndex == -1) endIndex = constant.indexOf(" };");
		String constantValue = constant.substring(constant.indexOf(" = ")
				+ " = ".length(), endIndex);
		if (DEBUG)
			writeLine("constantValue <" + constantValue + ">");
		constantValues[constantIndex] = constantValue;
	}

	// NS_IMETHOD SetStatus(PRUint32 statusType, const PRUnichar *status) = 0;
	// identify:
	// method name: <SetStatus>
	// Nbr of arguments: 2
	// Type of argument 0: PRUint32
	// Name of argument 0: statusType
	// Type of argument 1: const PRUnichar *
	// Name of argument 1: status
	void parseMethod(String line, int methodIndex) {
		int start = methodNameStartIndexOf(line);
		int end = methodNameEndIndexOf(line);
		String methodName = line.substring(start, end);
		if (DEBUG)
			writeLine("method name: <" + methodName + ">");
		methodNames[methodIndex] = methodName;
		int argStart = end+"(".length();
		int argEnd = line.indexOf(")", argStart);
		parseArgs(line.substring(argStart, argEnd), methodIndex);
	}

	// Given a line, returns the start of the method name or -1
	// if the line does not contain a method declaration.
	int methodNameStartIndexOf(String line) {
		for (int i = 0; i < BEFORE_METHOD_NAME.length; i++) {
			int index = line.indexOf(BEFORE_METHOD_NAME[i]);
			if (index != -1) return index + BEFORE_METHOD_NAME[i].length();
		}
		return -1;
	}
	int methodNameEndIndexOf(String line) {
		int startIndex = methodNameStartIndexOf(line);
		return line.indexOf("(", startIndex);
	}
	void parseArgs(String args, int methodIndex) {
		int nArgs = -1;
		// methods with no args look like: () or (void)
		String[] noArgs = new String[] { "", "void" };
		for (int i = 0; i < noArgs.length; i++) {
			if (args.equals(noArgs[i])) {
				nArgs = 0;
				break;
			}
		}
		if (nArgs == -1)
			nArgs = count(args, ", ") + 1;
		String[] argTypes = new String[nArgs];
		this.argTypes[methodIndex] = argTypes;
		String[] argNames = new String[nArgs];
		this.argNames[methodIndex] = argNames;
		int typeStart = 0;

		// name is separated from its type by either of the following (sorted by decreasing size to find the most complete pattern */
		String[] typeNameSep = new String[] { " * *", " **", " * & ", " * ", " *",
				" & ", " " };
		for (int i = 0; i < nArgs; i++) {
			/* get the type */
			int nextTypeStart = i < nArgs - 1 ? args.indexOf(", ", typeStart)
					+ ", ".length() : args.length();
			int typeNameSepIndex = 0;
			int separatorIndex = 0;
			for (; typeNameSepIndex < typeNameSep.length; typeNameSepIndex++) {
				separatorIndex = args.indexOf(typeNameSep[typeNameSepIndex],
						typeStart);
				if (separatorIndex != -1 && separatorIndex < nextTypeStart)
					break;
			}
			String separator = typeNameSep[typeNameSepIndex];
			argTypes[i] = getC2JavaType(args.substring(typeStart,
					separatorIndex + separator.length()));
			if (DEBUG)
				writeLine("arg type" + i + ": <" + argTypes[i] + ">");
			/* get the name */
			int nameStart = separatorIndex + separator.length();
			int nameEnd = i < nArgs - 1 ? args.indexOf(", ", nameStart) : args
					.length();
			argNames[i] = args.substring(nameStart, nameEnd);
			if (DEBUG)
				writeLine("arg name" + i + ": <" + argNames[i] + ">");

			typeStart = nextTypeStart;
		}
	}

	String getC2JavaType(String cType) {
		for (int i = 0; i < TYPES_C2JAVA.length; i++) {
			if (cType.indexOf(TYPES_C2JAVA[i][0]) != -1)
				return TYPES_C2JAVA[i][1];
		}
		return "!ERROR UNKNOWN C TYPE <" + cType + ">!";
	}

	// how many times part can be found in s
	static int count(String s, String part) {
		int index = -1, cnt = 0;
		while ((index = s.indexOf(part, index + 1)) != -1)
			cnt++;
		return cnt;
	}

	static String COPYRIGHTS =
		"/* ***** BEGIN LICENSE BLOCK *****\r\n"
		+ " * Version: MPL 1.1\r\n"
		+ " *\r\n"
		+ " * The contents of this file are subject to the Mozilla Public License Version\r\n"
		+ " * 1.1 (the \"License\"); you may not use this file except in compliance with\r\n"
		+ " * the License. You may obtain a copy of the License at\r\n"
		+ " * http://www.mozilla.org/MPL/\r\n"
		+ " *\r\n"
		+ " * Software distributed under the License is distributed on an \"AS IS\" basis,\r\n"
		+ " * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\r\n"
		+ " * for the specific language governing rights and limitations under the\r\n"
		+ " * License.\r\n"
		+ " *\r\n"
		+ " * The Original Code is Mozilla Communicator client code, released March 31, 1998.\r\n"
		+ " *\r\n"
		+ " * The Initial Developer of the Original Code is\r\n"
		+ " * Netscape Communications Corporation.\r\n"
		+ " * Portions created by Netscape are Copyright (C) 1998-1999\r\n"
		+ " * Netscape Communications Corporation.  All Rights Reserved.\r\n"
		+ " *\r\n" 
		+ " * Contributor(s):\r\n" 
		+ " *\r\n" 
		+ " * IBM\r\n"
		+ " * -  Binding to permit interfacing between Mozilla and SWT\r\n"
		+ " * -  Copyright (C) 2003 IBM Corp.  All Rights Reserved.\r\n"
		+ " *\r\n" + " * ***** END LICENSE BLOCK ***** */";

	static String PACKAGE_DECLARATION = "package org.eclipse.swt.internal.mozilla;";

}
