package edu.fiu.jtlex.data;


import java.io.FileInputStream;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.StringTokenizer;


import edu.fiu.jtlex.data.ILink.ALinkType;
import edu.fiu.jtlex.data.IEvent.EventClass;
import edu.fiu.jtlex.data.IInstance.Aspect;
import edu.fiu.jtlex.data.IInstance.Polarity;
import edu.fiu.jtlex.data.IInstance.Pos;
import edu.fiu.jtlex.data.IInstance.Tense;
import edu.fiu.jtlex.data.ILink.LinkTag;
import edu.fiu.jtlex.data.ILink.Origintype;
import edu.fiu.jtlex.data.ITimex.FunctionInDocument;
import edu.fiu.jtlex.data.ITimex.TimexMod;
import edu.fiu.jtlex.data.ITimex.TimexType;
import edu.fiu.jtlex.data.ILink.SLinkType;
import edu.fiu.jtlex.data.ILink.TLinkType;

/**
 * Default implementation of {@code ITimeMLParser}.
 * 
 * @author arada002
 */
public class TimeMLParser implements ITimeMLParser{
	private String rawText = "";
	private String text = "";
	private Set<IEvent> events = new HashSet<IEvent>();
	private Set<ITimex> timexes = new HashSet<ITimex>();
	private Set<ISignal> signals = new HashSet<ISignal>();
	private Set<IInstance> instances = new HashSet<IInstance>();
	private Set<ILink> links = new HashSet<ILink>();
	

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimeMLParser#parse(String InputStream)
	 */
	public IText parse(FileInputStream tmlFile) {
		
		Scanner scnr = new Scanner(tmlFile);
		
		while(scnr.hasNext()) {
			rawText += scnr.next();
			rawText += " ";
		}
		scnr.close();
		

			for(int i = 0; i <rawText.length(); i++){
				
				if (rawText.charAt(i) == '<') {
					// closing tag
					if (rawText.charAt(i+1) == '/') {
						String endTag = "";
						while(rawText.charAt(i) != '>' && i <= rawText.length() - 1) {
							endTag += String.valueOf(rawText.charAt(i));
							i++;
						}
						endTag += String.valueOf(rawText.charAt(i));
						//System.out.println("Endtag: " + endTag);
						if (endTag.contains("TimeML")) {
							break;
						}
						
					}
					
					else {
						String tag = "";
						String tagText = "";
						i++;
						while(rawText.charAt(i) != ' ' && rawText.charAt(i) != '>' &&  i <= rawText.length() - 1) {
							tag += String.valueOf(rawText.charAt(i));
							i++;
						}
						//System.out.println("Tag in else: " + tag);
						
						if(rawText.charAt(i) == '>') {
							continue;
						}
						else {
							i++;
							while(rawText.charAt(i) != '>' && i <= rawText.length() - 1) {
								//add text that is inside the tag
								tagText += String.valueOf(rawText.charAt(i));
								i++;
							}
							tagText += " ";
							i++;
							//System.out.println(tag + ": " + tagText);
							//these are at the beginning of the file
							if (tag.equals("?xml") || tag.equals("TimeML")) {
								i--;
							}
							else {
								while(rawText.charAt(i) != '<' && i <= rawText.length() - 1) {
									text += String.valueOf(rawText.charAt(i));
									tagText += String.valueOf(rawText.charAt(i));
									i++;
								}
								//System.out.print(tagText);
								i--;
								
								if(tag.equals("EVENT")) {
									
									if(rawText.substring(i+2, i+12).equals("NUMEX TYPE")) {
										i = i+12;
										while(rawText.charAt(i) != '>') {
											i++;
										}
										
										while(rawText.charAt(i) != '<') {
											text += String.valueOf(rawText.charAt(i));
											tagText += String.valueOf(rawText.charAt(i));
											i++;
										}
										i--;
									}
									else if(rawText.substring(i+2, i+13).equals("ENAMEX TYPE")) {
										i = i+12;
										while(rawText.charAt(i) != '>') {
											i++;
										}
										
										while(rawText.charAt(i) != '<') {
											text += String.valueOf(rawText.charAt(i));
											tagText += String.valueOf(rawText.charAt(i));
											i++;
										}
										i--;
									}
									else if(rawText.substring(i+1, i+11).equals("<CARDINAL>")) {
										i = i+11;
										while(rawText.charAt(i) != '<') {
											text += String.valueOf(rawText.charAt(i));
											tagText += String.valueOf(rawText.charAt(i));
											i++;
										}
										i--;
									}
									
									if(rawText.substring(i+1, i+9).equals("<VG-VBG>") || rawText.substring(i+1, i+9).equals("<VG-VBN>")) {
										i = i+9;
										while(rawText.charAt(i) != '<') {
											text += String.valueOf(rawText.charAt(i));
											tagText += String.valueOf(rawText.charAt(i));
											i++;
										}
										i--;
									}
									if(rawText.substring(i+1, i+5).equals("<VG>") || rawText.substring(i+1, i+5).equals("<NG>")|| rawText.substring(i+1, i+5).equals("<JG>")|| rawText.substring(i+1, i+5).equals("<PG>")) {
										i = i+5;
										
										while(rawText.charAt(i) != '<') {
											text += String.valueOf(rawText.charAt(i));
											tagText += String.valueOf(rawText.charAt(i));
											i++;
										}
										i--;
									}
									
									if(rawText.substring(i+1, i+7).equals("<HEAD>")) {
										i = i+7;
										while(rawText.charAt(i) != '<') {
											text += String.valueOf(rawText.charAt(i));
											tagText += String.valueOf(rawText.charAt(i));
											i++;
										}
										i--;
									}
									//System.out.println(tagText);
									events.add(parseEvent(tagText));
								}
								else if(tag.equals("TIMEX3")) {
									//System.out.println(rawText.substring(i+1, i+11));
									if(rawText.substring(i+1, i+11).equals("<CARDINAL>")) {
										i = i+11;
										while(rawText.charAt(i) != '<') {
											text += String.valueOf(rawText.charAt(i));
											tagText += String.valueOf(rawText.charAt(i));
											i++;
										}
										i--;
									}
									
									timexes.add(parseTimex(tagText));
								}
								else if(tag.equals("SIGNAL")) {
									if(rawText.substring(i+1, i+11).equals("<CARDINAL>")) {
										i = i+11;
										while(rawText.charAt(i) != '<') {
											text += String.valueOf(rawText.charAt(i));
											tagText += String.valueOf(rawText.charAt(i));
											i++;
										}
										i--;
									}
									//System.out.println(rawText.substring(i+1, i+5));
									if(rawText.substring(i+1, i+5).equals("<PG>") || rawText.substring(i+1, i+5).equals("<RG>") || rawText.substring(i+1, i+5).equals("<VG>")) {
										i = i+5;
										while(rawText.charAt(i) != '<') {
											text += String.valueOf(rawText.charAt(i));
											tagText += String.valueOf(rawText.charAt(i));
											i++;
										}
										i--;
									}
									signals.add(parseSignal(tagText));
								}
								else if(tag.equals("MAKEINSTANCE")) {
									instances.add(parseInstance(tagText));
								}
								else if(tag.contains("LINK")) {
									links.add(parseLink(tag, tagText));
								}
								
								//System.out.println(tag + " " + tagText);
							}
							
							
						}
					}
				}
				
				else {
					text += String.valueOf(rawText.charAt(i));
				}
			}
			//System.out.println(text);
	
			return new Text(rawText, text, timexes,
			links, instances);
		} 
		

	

	   
	  
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimeMLParser#parseEvent(String eventString)
	 */
	public IEvent parseEvent(String eventString){
		int eid = 0;
		EventClass eClass = null;
		String stem = "";
		StringTokenizer tok = new StringTokenizer(eventString);
		while(tok.hasMoreTokens()) {
			String token = tok.nextToken();
			if(token.contains("eid=\"")) {
				eid = Integer.parseInt(token.substring(token.indexOf('"') + 2, token.length()-1));
			}
			else if (token.contains("class=\"")) {
				eClass = EventClass.valueOf(token.substring(token.indexOf('"') + 1, token.length()-1));
			}
			else if (token.contains("stem=\"")) {
				if(token.indexOf('"') != token.lastIndexOf('"')) {
					stem += token.substring(token.indexOf('"') + 1, token.lastIndexOf('"')) + " ";
				}
				else {
					stem += token.substring(token.indexOf('"') + 1) + " ";
				}
			}
			else {
				stem += token + " ";
			}
		}
		//System.out.println("Eid: " + eid + " eClass: " + eClass.toString() + " stem: " + stem);
		
		return new Event(eid, eClass, stem);
	}
	
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimeMLParser#parseTimex(String timexString)
	 */
	public ITimex parseTimex(String timexString){
		int tid = 0;
		TimexType type = null;
		String value = "";
		TimexMod mod = null;
		boolean temporalFunction = true;
		int anchorId = 0;
		FunctionInDocument documentFunction = null;
		int beginPoint = 0;
		int endPoint = 0; 
		String quant = null;
		String freq = null;
		String phrase = "";
		
		StringTokenizer tok = new StringTokenizer(timexString);
		
		while(tok.hasMoreTokens()) {
			String token = tok.nextToken();
			if(token.contains("tid=\"")) {
				tid = Integer.parseInt(token.substring(token.indexOf('"') + 2, token.length()-1));
			}
			else if (token.contains("type=\"")) {
				type = TimexType.valueOf(token.substring(token.indexOf('"') + 1, token.length()-1));
			}
			else if (token.contains("value=\"")) {
				if(token.indexOf('"') != token.lastIndexOf('"')) {
					value += token.substring(token.indexOf('"') + 1, token.lastIndexOf('"')) + " ";
				}
				else {
					value += token.substring(token.indexOf('"') + 1) + " ";
				}
			}
			else if (token.contains("mod=\"")) {
				mod = TimexMod.valueOf(token.substring(token.indexOf('"') + 1, token.length()-1));
			}
			else if (token.contains("temporalFunction=\"")) {
				temporalFunction = Boolean.parseBoolean(token.substring(token.indexOf('"') + 1, token.lastIndexOf('"')));
				}
			else if(token.contains("anchorTimeID=\"")) {
				anchorId = Integer.parseInt(token.substring(token.indexOf('"') + 2, token.length()-1));
			}
			else if (token.contains("functionInDocument=\"")) {
				documentFunction = FunctionInDocument.valueOf(token.substring(token.indexOf('"') + 1, token.length()-1));
			}
			else if(token.contains("beginPoint=\"")) {
				beginPoint = Integer.parseInt(token.substring(token.indexOf('"') + 2, token.length()-1));
			}
			else if(token.contains("endPoint=\"")) {
				endPoint = Integer.parseInt(token.substring(token.indexOf('"') + 2, token.length()-1));
			}
			else if (token.contains("freq=\"")) {
				freq = token.substring(token.indexOf('"') + 1, token.lastIndexOf('"')) + " ";
				}
			else if (token.contains("quant=\"")) {
				quant = token.substring(token.indexOf('"') + 1, token.lastIndexOf('"')) + " ";
				}
			else {
				phrase += token + " ";
			}
		}
		//System.out.println("tid: " + tid + " type: " +type + " value: " + value + " mod: " + mod + " anchorID: " + anchorId +
				//" docFunction: " + documentFunction + " beginPoint: " + beginPoint + " endPoint: " + endPoint + " freq: " + freq + " quant: " + quant + " phrase: " + phrase);
		
		return new Timex(tid, type, value, mod, temporalFunction, anchorId, documentFunction,
				beginPoint, endPoint, quant, freq, phrase);
	}
	
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimeMLParser#parseLink(String linkString)
	 */
	public ILink parseLink(String tag,String linkString){
		int lid = 0;
		String syntax = "";
		INode firstNode = null;
		ISignal signal = null;
		INode secondNode = null;
		Origintype origin = null;
		LinkTag linkTag = null;
		ILinkType relType = null;
		
		if (tag.contains("ALINK")) {
			linkTag = LinkTag.ALINK;
		}
		else if (tag.contains("SLINK")) {
			linkTag = LinkTag.SLINK;
		}
		else if (tag.contains("TLINK")) {
			linkTag = LinkTag.TLINK;
		}
		StringTokenizer tok = new StringTokenizer(linkString);
		while(tok.hasMoreTokens()) {
			String token = tok.nextToken();
			
			if(token.contains("lid=\"")) {
				lid = Integer.parseInt(token.substring(token.indexOf('"') + 2, token.length()-1));
			}
			else if (token.contains("syntax=\"")) {
				syntax = token.substring(token.indexOf('"') + 1, token.lastIndexOf('"'));
			}
			else if (token.contains("eventInstanceID=\"")) {
				int eiid = Integer.parseInt(token.substring(token.indexOf('"') + 3, token.length()-1));
				for (IInstance instanceObj: instances) {
					if (instanceObj.getId() == eiid) {
						firstNode = instanceObj;
					}
				}
			}
			else if (token.contains("timeID=\"")) {
				int tid = Integer.parseInt(token.substring(token.indexOf('"') + 2, token.length()-1));
				for (ITimex timexObj: timexes) {
					if (timexObj.getId() == tid) {
						firstNode = timexObj;
					}
				}
			}
			else if (token.contains("relatedToEventInstance=\"") || token.contains("subordinatedEventInstance=\"")) {
				int eiid = Integer.parseInt(token.substring(token.indexOf('"') + 3, token.lastIndexOf('"')));
				for (IInstance instanceObj: instances) {
					if (instanceObj.getId() == eiid) {
						secondNode = instanceObj;
					}
				}
			}
			else if (token.contains("relatedToTime=\"")) {
				int tid = Integer.parseInt(token.substring(token.indexOf('"') + 2, token.lastIndexOf('"')));
				for (ITimex timexObj: timexes) {
					if (timexObj.getId() == tid) {
						secondNode = timexObj;
					}
				}
			}
			else if (token.contains("signalID=\"")) {
				int sid = Integer.parseInt(token.substring(token.indexOf('"') + 2, token.lastIndexOf('"')));
				for (ISignal signalObj: signals) {
					if (signalObj.getID() == sid) {
						signal = signalObj;
					}
				}
			}
			else if (token.contains("origin=\"")) {
				origin = Origintype.valueOf(token.substring(token.indexOf('"') + 1, token.lastIndexOf('"')));
			}
			else if (token.contains("relType=\"")) {
				if(linkTag == LinkTag.ALINK) {
					relType = ALinkType.valueOf((token.substring(token.indexOf('"') + 1, token.lastIndexOf('"'))));
				}
				else if(linkTag == LinkTag.SLINK) {
					relType = SLinkType.valueOf((token.substring(token.indexOf('"') + 1, token.lastIndexOf('"'))));
				}
				else if(linkTag == LinkTag.TLINK) {
					relType = TLinkType.valueOf((token.substring(token.indexOf('"') + 1, token.lastIndexOf('"'))));
				}
			}
		}
		
		if(linkTag == LinkTag.TLINK) {
			return new Link(linkTag, lid, syntax,firstNode, signal, secondNode,
					relType, origin);
		}
		else{
			return new Link(linkTag, lid, syntax, firstNode, signal, secondNode,
					relType);
		}
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimeMLParser#parseInstance(String instanceString)
	 */
	public IInstance parseInstance(String instanceString){
		int eiid = 0;
		IEvent event = null;
		Tense tense = null;
		Aspect aspect = null;
		Pos pos = null;
		Polarity polarity = null;
		String modality = null;
		ISignal signal = null;
		String cardinality = null; 
		
		StringTokenizer tok = new StringTokenizer(instanceString);
		
		while(tok.hasMoreTokens()) {
			String token = tok.nextToken();
			if(token.contains("eiid=\"")) {
				eiid = Integer.parseInt(token.substring(token.indexOf('"') + 3, token.length()-1));
			}
			else if(token.contains("eventID=\"")) {
				int eid = Integer.parseInt(token.substring(token.indexOf('"') + 2, token.length()-1));
				for (IEvent eventObj: events) {
					if (eventObj.getId() == eid) {
						event = eventObj;
					}
				}
			}
			else if (token.contains("tense=\"")) {
				tense = Tense.valueOf(token.substring(token.indexOf('"') + 1, token.length()-1));
			}
			else if (token.contains("aspect=\"")) {
				aspect = Aspect.valueOf(token.substring(token.indexOf('"') + 1, token.length()-1));
			}
			else if (token.contains("pos=\"")) {
				pos = Pos.valueOf((token.substring(token.indexOf('"') + 1, token.lastIndexOf('"'))));
			}
			else if (token.contains("polarity=\"")) {
				polarity = Polarity.valueOf(token.substring(token.indexOf('"') + 1, token.length()-1));
			}
			else if (token.contains("modality=\"")) {
				if(token.indexOf('"') != token.lastIndexOf('"')) {
					modality = token.substring(token.indexOf('"') + 1, token.lastIndexOf('"')) + " ";
				}
				else {
					if(modality == null) {
						modality = "";
					}
					modality += token.substring(token.indexOf('"') + 1, token.length()-1);
				}
			}
			else if(token.contains("signalID=\"")) {
				int sid = Integer.parseInt(token.substring(token.indexOf('"') + 4, token.length()-1));
				for (ISignal signalObj: signals) {
					if (signalObj.getID() == sid) {
						signal = signalObj;
					}
				}
			}
			else if(token.contains("cardinality=\"")) {
				cardinality = token.substring(token.indexOf('"') + 1, token.length()-1);
			}
		}

		return new Instance(eiid, event, tense, aspect, pos, polarity, modality, signal, cardinality);

	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimeMLParser#parseLink(String signalString)
	 */
	public ISignal parseSignal(String signalString) {
		int sid = 0;
		String signalStr = "";
		
		StringTokenizer tok = new StringTokenizer(signalString);
		
		while(tok.hasMoreTokens()) {
			String token = tok.nextToken();
			if(token.contains("sid=\"")) {
				sid = Integer.parseInt(token.substring(token.indexOf('"') + 2, token.length()-1));
			}
			else {
				signalStr += token;
			}
		}
		return new Signal(sid, signalStr);
	}


	
}
