/*
 *   Copyright 2003-2004 The Apache Software Foundation.
// (c) Copyright IBM Corp. 2004, 2005 All Rights Reserved
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
package org.apache.axis.tools.common;
import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.StringTokenizer;

public class InputCppSourceCode {

	private ArrayList parts = new ArrayList();
	private String name;

	public InputCppSourceCode(BufferedReader br, String name) throws Exception {
		this.name = name;

		String s = null;
		StringBuffer buff = new StringBuffer();
		for (int i = 1;; i++) {
			try {
				s = br.readLine();
			} catch (Exception e) {
				System.err.println(
					"Ignoring exception thrown parsing file "
						+ name
						+ " line number "
						+ i);
				e.printStackTrace();
				break;
			}
			if (s == null)
				break;
			buff.append(s + "\n");
		}
		String str = buff.toString();

		// TODO: When checking for rest.startsWith("struct") should
		// check the next letter after struct is not alphanumeric otherwise
		// we'll get false matches on a function called structify() for 
		// instance. Also applies to enum, union, public, typedef, etc

		String rest, text = "";
		int scopedepth = 0;
		String scope = "public";
		String currentClass = null;
		for (int idx = 0; idx < str.length(); /* No idx++ */
			) {
			rest = str.substring(idx);
			if (Character.isWhitespace(rest.charAt(0))) {
				int ridx = 0;
				while (ridx < rest.length()
					&& Character.isWhitespace(rest.charAt(ridx)))
					ridx++;
				text = rest.substring(0, ridx);
				FilePart fp = new FilePart(text, FilePart.WHITESPACE);
				parts.add(fp);
				idx += ridx;

			} else if (rest.startsWith("/*")) {
				int ridx = rest.indexOf("*/"); // Don't use Utils here
				text = str.substring(idx, idx + ridx + 2);
				FilePart fp = new FilePart(text, FilePart.COMMENT);
				parts.add(fp);
				idx += text.length();

			} else if (rest.startsWith("//")) {
				text = str.substring(idx, idx + rest.indexOf("\n"));
				FilePart fp = new FilePart(text, FilePart.COMMENT);
				parts.add(fp);
				idx += text.length();

			} else if (rest.startsWith("#")) {
				int ridx = rest.indexOf("\n");
				char c = rest.charAt(ridx - 1);
				while (-1 != ridx && '\\' == c) {
					String rest2 = rest.substring(ridx + 1);
					ridx += rest2.indexOf("\n") + 1;
					c = rest.charAt(ridx - 1);
				}
				text = str.substring(idx, idx + ridx);
				FilePart fp = new FilePart(text, FilePart.DIRECTIVE);
				parts.add(fp);
				idx += text.length();

			} else if (rest.startsWith("}")) {
				if (scopedepth <= 0)
					Utils.rude(
						"Braces do not match",
						name,
						lineNo(str, idx),
						rest.substring(0, rest.indexOf("\n")));
				else
					scopedepth--;
				// TODO: better checking that this brace really ends the class
				if (0 == scopedepth)
					currentClass = null;
				scope = "public";
				parts.add(new FilePart("}", FilePart.ENDSCOPE));
				idx++;

			} else if (rest.startsWith(";")) {
				parts.add(new FilePart(";", FilePart.FIELD));
				idx++;

			} else if (
				!Character.isLetter(rest.charAt(0))
					&& '~' != rest.charAt(0)
					&& '_' != rest.charAt(0)) {
				Utils.rude(
					"Lines must start with a letter ",
					name,
					lineNo(str, idx),
					rest.substring(0, rest.indexOf("\n")));

			} else if (MacroPart.isAMacro(rest)) {
				MacroPart mp = MacroPart.create(rest);
				parts.add(mp);
				idx += mp.length();

			} else if (beginsScope(rest)) {
				scopedepth++;
				text = rest.substring(0, Utils.indexOf(rest, "{") + 1);
				FilePart fp = new FilePart(text, FilePart.BEGINSCOPE);
				parts.add(fp);
				idx += text.length();
				if (Utils.startsWith(text, "class")) {
					// TODO: cope with comments here
					// TODO: split out classes into a ClassPart 
					StringTokenizer st =
						new StringTokenizer(text, Utils.whitespace + ":");
					st.nextToken(); // step over "class"
					while (st.hasMoreTokens()) {
						String word = st.nextToken();
						if (Configuration.isAttribute(word))
							continue;
						currentClass = word;
						break;
					}
				}

			} else if (isEnumOrUnion(rest)) {
				int ridx = Utils.findMatching(rest, '{', '}') + 1;
				String rest2 = rest.substring(ridx);
				ridx = idx + ridx + Utils.indexOf(rest2, ';') + 1;
				text = str.substring(idx, ridx);
				FilePart fp = new FilePart(text, FilePart.ENUM);
				parts.add(fp);
				idx += text.length();

			} else if (
				scopedepth > 0
					&& (rest.startsWith("public")
						|| rest.startsWith("protected")
						|| rest.startsWith("private"))) {
				int colon = rest.indexOf(":");
				if (-1 == colon)
					Utils.rude(
						"No colon found after public or private ",
						name,
						lineNo(str, idx),
						rest.substring(0, rest.indexOf("\n")));
			    scope = str.substring(idx, idx + colon);
				text = str.substring(idx, idx + colon + 1);
				FilePart fp = new FilePart(text, FilePart.CLASSATTRIBUTE);
				parts.add(fp);
				idx += text.length();

			} else if (Utils.startsWith(rest, "typedef")) {
				int semicolon = Utils.indexOf(rest, ';');
				int brace = Utils.indexOf(rest, '{');

				if (-1 == semicolon)
					Utils.rude(
						"No semicolon found after typedef",
						name,
						lineNo(str, idx),
						rest.substring(0, rest.indexOf("\n")));

				if (-1 == brace || semicolon < brace) {
					// Simple typedef
					text = str.substring(idx, idx + semicolon + 1);
				} else {
					// Typedef of a struct, etc
					int endbrace = Utils.findMatching(rest, '{', '}');
					String rest2 = rest.substring(endbrace);
					semicolon = Utils.indexOf(rest2, ';');
					text = str.substring(idx, idx + endbrace + semicolon + 1);
				}
				FilePart fp = new FilePart(text, FilePart.TYPEDEF);
				parts.add(fp);
				idx += text.length();

			} else {
				if (isMethod(rest)) {

					int brace = Utils.indexOf(rest, '{');
					Signature signature =
						new Signature(str.substring(idx, idx + brace));
					if (signature.failed())
						Utils.rude(
							"Signature parsing failed",
							name,
							lineNo(str, idx),
							signature.getOriginal());
					if (null != currentClass
						&& null == signature.getClassName())
						signature.setClassName(currentClass);
				    signature.setScope(scope);

					String body = rest.substring(brace);
					int endBrace = Utils.findMatching(body, '{', '}');
					body = body.substring(0, endBrace + 1);
					int endIdx =
						idx + signature.originalLength() + body.length();
					text = str.substring(idx, endIdx);
					MethodPart mp =
						new MethodPart(text, signature, body);
					parts.add(mp);
					idx += text.length();

				} else if (isField(rest)) {
					int semicolon = Utils.indexOf(rest, ';');
					text = str.substring(idx, idx + semicolon + 1);
					FilePart fp = new FilePart(text, FilePart.FIELD);
					parts.add(fp);
					idx += text.length();

				} else if (isPrototype(rest)) {
					int semicolon = Utils.indexOf(rest, ';');
					text = str.substring(idx, idx + semicolon + 1);
					PrototypePart pp = new PrototypePart(text, currentClass);
					pp.setScope(scope);
					parts.add(pp);
					idx += text.length();

				} else {
					//TODO other file parts here - not sure if there are any others?
					Utils.rude(
						"Unrecognised file part",
						name,
						lineNo(str, idx),
						rest.substring(0, rest.indexOf("\n")));
				} // end if
			} // end if
		} // end for
	}

	public Iterator getPartIterator() {
		return parts.iterator();
	}

	private int lineNo(String s, int idx) {
		int n = 0;
		for (int i = 0; i < idx && i < s.length(); i++)
			if ('\n' == s.charAt(i))
				n++;
		return n;
	}

	/**
	 * Find out whether we are defining a class, struct or extern "C" which
	 * may contain function implementations. These will have braces which 
	 * begin a new scope. Ignore function prototypes that return a struct.
	 * struct mystr { int f1; };
	 * struct mystr func();
	 * struct mystr func() { struct mystr a; return a; }
	 */
	private static boolean beginsScope(String s) throws ParsingException {
		if (isMethod(s))
			return false;

		int brace = Utils.indexOf(s, '{');
		int semicolon = Utils.indexOf(s, ';');

		// Return false for class prototypes, but true for class definitions.
		if (Utils.startsWith(s, "class")) {
			if (-1 == brace)
				return false;
			if (-1 == semicolon)
				return true;
			return brace < semicolon;
		}

		if (Utils.startsWith(s, "struct")) {
			if (-1 == brace || -1 == semicolon)
				return false;
			return brace < semicolon;
		}
		return startsWithExternScope(s);
	}

	/**
	 * There are 4 types of extern ...
	 * extern int field;
	 * extern int func();
	 * extern "C" int func() { return 2; }
	 * extern "C" { int func() { return 2; } }
	 * This method should return true only for the last of these three
	 * examples since only the last one creates a new scope using braces.
	 */
	private static boolean startsWithExternScope(String s)
		throws ParsingException {
		if (!s.startsWith("extern"))
			return false;

		int brace = Utils.indexOf(s, '{');
		int semicolon = Utils.indexOf(s, ';');
		int bracket = Utils.indexOf(s, '(');

		if (-1 == brace)
			return false;
		return (-1 == semicolon || brace < semicolon)
			&& (-1 == bracket || brace < bracket);
	}

	/**
	 * Find out whether we are defining an enum or union which will contain
	 * braces. Ignore function prototypes that return an enum or union.
	 * enum colour { red, blue };
	 * enum colour func();
	 * enum colour func() { return colour.red; }
	 */
	private static boolean isEnumOrUnion(String s) throws ParsingException {
		if ((!Utils.startsWith(s, "enum") && !Utils.startsWith(s, "union"))
			|| isMethod(s))
			return false;

		int brace = Utils.indexOf(s, '{');
		int semicolon = Utils.indexOf(s, ';');
		return -1 != brace && (-1 == semicolon || brace < semicolon);
	}

	/** 
	 * Rules to recognise fields and methods...
		 *
		 * Fields must contain a semicolon
	 * Methods may or may not contain a semicolon
	 * Prototypes must contain a semicolon
	 * Fields may or may not contain a brace (array initialisers do)
	 * Methods must contain a brace
	 * Prototypes must not contain a brace
	 * Fields may or may not contain a bracket (casts do)
	 * Methods must contain a bracket
	 * Prototypes must contain a bracket
	 *
	 * It's a method if it contains a bracket and then a brace
	 * before the first semicolon (if there is a semicolon). 
	 * It's a prototype if it's not a method and it contains brackets before a semicolon.
	 * It's a field if it's not a method or a prototype and it contains a semicolon.
	 * If it's not a field, a method or a prototype and we haven't recognised it
	 * previously then it's an error.
	 */
	private static boolean isMethod(String s) throws ParsingException {
		int semicolon = Utils.indexOf(s, ';');
		int brace = Utils.indexOf(s, '{');
		int bracket = Utils.indexOf(s, '(');

		return (
			-1 != bracket
				&& -1 != brace
				&& bracket < brace
				&& (-1 == semicolon || brace < semicolon));
	}

	private static boolean isPrototype(String s) throws ParsingException {
		int semicolon = Utils.indexOf(s, ';');
		int bracket = Utils.indexOf(s, '(');
		return !isMethod(s)
			&& -1 != semicolon
			&& -1 != bracket
			&& bracket < semicolon;
	}

	private static boolean isField(String s) throws ParsingException {
		int semicolon = Utils.indexOf(s, ';');
		return !isMethod(s) && !isPrototype(s) && -1 != semicolon;
	}
	
	public String getName() {
		return name;
	}

	public String toString() {
		StringBuffer text = new StringBuffer();
		for (int i = 0; i < parts.size(); i++) {
			text.append(((FilePart) (parts.get(i))).toString());
		}
		return text.toString();
	}

}
