package org.etsi.t3d;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.LinkedList;

import org.etsi.common.logging.LoggingConfiguration;
import org.etsi.common.logging.LoggingInterface;
import org.etsi.common.logging.LoggingInterface.MessageClass;


import elements.*;
public class XMLPrinter {
	private String currentTTCN3File;
	private PrintStream stream;
	private LinkedList<String> modules = new LinkedList<String>();
	private int files = 0;
	private String currentModule;
	private LinkedList <String[]> descs = new LinkedList<String[]>();

	private LoggingInterface logger = null;
	
	public XMLPrinter(){
		this.logger = new LoggingInterface(T3D.activeProfile.getLoggingConfiguration());
		this.logger.setMaximumLogLevel(T3D.getLogLevel());
	}
	
	public int getFileCount(){
		return files;
	}
	
	public void setXMLPath(String xmlpath){
		FileOutputStream file;
		try {
			file = new FileOutputStream(xmlpath);
			stream = new PrintStream(file);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}		
		writeStream("\n<project t3dversion=\"" + T3D.versionNumber + "\">");		
	}
	//adds String content to project.xml
	private void writeStream(String content){
		stream.print(content);
	}
	//adds XML representation of element to project.xml
	public void printElement(TTCN3Element element, int line){
		addDescriptions(element.getDescs());
		writeStream("\n" + element.toXML(currentModule));
		files++;
		if(element.getType().equals("testcase") || element.getType().equals("parameter"))
			files++;
	}
	// 0 = desc, 1 = file, 2 = line
	private void addDescriptions(LinkedList<String[]> descs){
		for(String[] desc : descs){			
			if(!descsContain(desc))
				this.descs.add(desc);
		}
	}
	
	private boolean descsContain(String[] desc){
		for(String[] stringArray : descs)
			if(stringArray[0].equals(desc[0])){
				//TODO: out of place here, needs to be moved
				if (T3D.activeProfile.isCheckIdenticalDescriptionTags()) {
					String warning = "Identical @desc tag found: \""
							+ desc[0].replaceAll("\\n", " ")
							+ "\" ("
							+ stringArray[1]
							+ " "
							+ stringArray[2]
							+ ")";
					this.getLoggingInterface()
						.logWarning(Integer.valueOf(desc[2]).intValue(),
								Integer.valueOf(desc[2]).intValue(),
								MessageClass.DOCUMENTATION,
								warning);
					// TODO: revise XML usage
					// T3D.printLog(LEVEL0, getCurrentTTCN3File(),
					// Integer.valueOf(desc[2]).intValue(),
					// Integer.valueOf(desc[2]).intValue(), 1, warning);
				}
				return true;
			}
		return false;
	}
	
	
	//adds XML representation of a module to project.xml and prints warnings
	public void printModule(String name, TTCN3Comment comment, String behaviour, int line){
		if (modules.contains(name)) {
			int repetitionIndex = 0; 
			while(modules.contains(name + "_"+repetitionIndex)){
				repetitionIndex++;
			}
			this.getLoggingInterface().logWarning(line,
					line,
					MessageClass.DOCUMENTATION,
					"Module \""+name+"\" (in file \""+this.getCurrentTTCN3File()+"\") is declared multiple times. The instance will be refererred to as \""+name+"_"+repetitionIndex+"\"!");

			printModule(name+"_"+repetitionIndex,comment, behaviour, line);
			modules.add(name+"_"+repetitionIndex);
		} else {
			writeStream("\n<module>\n<name>" + name + "</name>" + comment.toString()
					+ "<behaviour>" + behaviour.replaceAll("<tab/>", "     ") + "</behaviour>"
					+ "<modulename>" + name + "</modulename>"
					+ "\n</module>");
			modules.add(name);
			files += 3;
			currentModule = name;
			for (String warning : comment.getWarnings()) {
				this.getLoggingInterface().logWarning(line,
						line,
						MessageClass.DOCUMENTATION,
						warning);
				// TODO: revise XML usage
				// T3D.printLog(LEVEL0, getCurrentTTCN3File(), line, line, 1,
				// warning);
			}
		}
	}
	
	//adds XML representation of a group to project.xml
	public void printGroup(String name, String location, TTCN3Comment comment, String behaviour, String path, int line){
			writeStream("\n<group>\n<name>" + name + "</name>\n"
				+ "<location>" + location + "</location>"
				+ comment.toString()
				+ "<behaviour>" + behaviour.replaceAll("<tab/>", "     ") + "</behaviour>"
				+ "<modulename>" + currentModule + "</modulename>"
				+ path
				+ "\n</group>");
			files += 2;
	}
	//adds <file> elements to project.xml finishes the root element
	public void finishXML(){
		files = files + 3;
		writeStream("\n</project>");
	}
	
	public void setCurrentTTCN3File(String currentTTCN3File) {
		this.currentTTCN3File = currentTTCN3File;
	}

	public String getCurrentTTCN3File() {
		return currentTTCN3File;
	}

	public void setLoggingInterface(LoggingInterface logger) {
		this.logger = logger;
	}

	public LoggingInterface getLoggingInterface() {
		return logger;
	}
	
}
