package nl.wouterd;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class LUAtoXML {
	
	public static int LUA2XML_MODE_ROOT = 0;
	public static int LUA2XML_MODE_TREE = 1;

	private static int getRightSideEnd(String s) {

		int i = 0;
		boolean inString = false;
		
		while (i < s.length() && (s.charAt(i) != ',' || inString)) {
			
			if (s.charAt(i) == '"' && (i == 0 || s.charAt(i - 1) != '\\')) {
				inString = (inString?false:true);
			}
			
			i++;
			
		}
		
		return i;
		
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		
		// Need at least an input filename specified
		if (args.length < 1) {
			System.out.println("ERROR - Please specify an input file\n");
			return;
		}
		
		String inputFilename = args[0];
		System.out.println("Input file: " + inputFilename + "\n");

		// If no second (output) file is specified, make one up ourselves
		String outputFilename = inputFilename + ".xml";
		
		// If an output filename is specified, use that one instead
		if (args.length >= 2) {
			outputFilename = args[1];
		}
		
		System.out.println("Output file: " + outputFilename);
		
		BufferedReader input = new BufferedReader(new FileReader(inputFilename));
		
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document xmlDoc = builder.newDocument();
		Element xmlRoot = xmlDoc.createElement("LUA");
		xmlDoc.appendChild(xmlRoot);
		
		String line = input.readLine();
		int mode = LUA2XML_MODE_ROOT;
		Element current = xmlRoot;
		while (null != line) {
			
			line = line.trim();
			
			// See what we got, we should have a variable name first
			while (!line.equals("")) {
				
				// End of an object
				if (line.charAt(0) == '}') {
					
					current = (Element) current.getParentNode();
					
					// Check if we are back at the root
					if (current == xmlRoot) {
						
						mode = LUA2XML_MODE_ROOT;
						
					}
					
					// No comma if it's the end of a root element (stupid LUA =])
					if (mode == LUA2XML_MODE_ROOT) {
						
						if (line.length() < 2) {
							line = "";
						}
						else {
							line = line.substring(1).trim();
						}
						
					}
					// Search for the comma and cut everything before it and including it off
					else {
						
						int rEnd = getRightSideEnd(line);
						
						if (rEnd >= line.length()) {
							line = "";
						}
						else {
							line = line.substring(rEnd + 1);
						}
						
					}
					
				}
				// Normal stuff
				else {
					
					int pos = line.indexOf("=");
					if (pos == -1) {
						System.out.println("Line: " + line);
						throw new Exception("Cannot parse this - no '=' in line");
					}
				
					String lPart = line.substring(0, pos - 1).trim();
					String rPart = line.substring(pos + 1).trim();

					String varName;
					
					if (mode == LUA2XML_MODE_ROOT) {
						
						varName = lPart;
						
					}
					else if (mode == LUA2XML_MODE_TREE) {
					
						if (lPart.length() < 4 || !lPart.substring(0,2).equals("[\"") || !lPart.substring(lPart.length() - 2).equals("\"]")) {
							
							// Maybe not just a counter?
							if (lPart.length() < 3 || lPart.charAt(0) != '[' && lPart.charAt(lPart.length()-1) != ']') {
								
								System.out.println("I cannot process this descriptor: " + lPart);
								throw new Exception("argh!");
								
							}
							else {
								
								varName = "Item" + lPart.substring(1, lPart.length() - 1);
								
							}
							
						}
						else {
					
							varName = lPart.substring(2, lPart.length() - 2);
							
						}
					}
					else {
						throw new Exception("Developer ERROR - Unknown LUA Parcer Mode");
					}
					
					Element newElement = xmlDoc.createElement("Node");
					newElement.setAttribute("name", varName);
					current.appendChild(newElement);
					current = newElement;
					
					mode = LUA2XML_MODE_TREE;
					
					// If it's not opening a new object, put a text node in 
					if (rPart.charAt(0) == '{') {
						
						if (rPart.length() < 2) {
							line = "";
						}
						else {
							line = rPart.substring(1);
						}
						
					}
					// Create a text node
					else {
						int rEnd = getRightSideEnd(rPart);
					
						if (rEnd >= rPart.length()) {
							line = "";
						}
						else {
							line = rPart.substring(rEnd + 1);
						}
						
						String outText = rPart.substring(0, rEnd);
						
						current.appendChild(xmlDoc.createTextNode(outText));
						current = (Element) current.getParentNode();
						
						// Check if we are back at the root
						if (current == xmlRoot) {
							
							mode = LUA2XML_MODE_ROOT;
							
						}
					}
					
					//System.out.println(++i + " Left: '" + lPart + "', Right: '" + rPart + "', Line: '" + line + "'");
				
				}
				
			}

			line = input.readLine();
			//System.out.println(++i + " : EMPTY");
								
		}
		
		input.close();
		
		System.out.print("Input File Read, outputting to output..");
		
		TransformerFactory tFactory = TransformerFactory.newInstance();
		Transformer trans = tFactory.newTransformer();
		
		File outFile = new File(outputFilename);
		if (outFile.exists())
			outFile.delete();
		
		outFile.createNewFile();
		FileWriter writer = new FileWriter(outFile);
		
		DOMSource source = new DOMSource(xmlDoc);
		StreamResult res = new StreamResult(writer);
		trans.transform(source, res);
		
		writer.close();
		
		System.out.println(" Done!");
	}

}
