package edu.fiu.jtlex.data;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
 * Represents a Timeline of a TimeML graph, which is an ordered list of the events
 * extracted from a  TimeML Graph. TimeML annotations are converted into a collection of
 * main and subordinated timelines arranged into a trunk-and-branch style structure.
 * This class takes an ordered timeline, a set of attachment links, and an array list of partitioned graphs,
 * arranging  them into a Timeline. 
 * 
 * @author Emmanuel Garcia
 */
public class Timeline implements Iterator<String> {
	
	private List<String> MainTimeline;
	private List<String> attachmentPoints;
	private ArrayList<List<String>> Timelines;
	private ArrayList<List<String>> SubordinationTimelines;
	private Set<ILink> singleSlinks;
	private int currentPosition;
	private int totalTimepoints;

	/**
	 * @param ArrayList<List<String>> produced by the Solve() method in the GraphTCSP.java class.
	 * @param singleSlinks, Set<ILink> produced by the partitionLinks() method in the IGraphPartitioner.java class.
	 */
	public Timeline(ArrayList<List<String>>Timeline, Set<ILink> singleSlinks){
		this.Timelines = Timeline;
		this.singleSlinks = singleSlinks;
		totalTimepoints = 0;
		SubordinationTimelines = new ArrayList<>();
		countTimepoints();
		initializeMainTimeline();
		initializeSubordinationTimelines();
		if(singleSlinks != null)
			initializeAttachmentPoints();
		currentPosition = 0;
	}
	
	
	/**
	 * @return true if there are Timeline elements remaining on the List
	 */
	public boolean hasNext() {
		if(currentPosition < MainTimeline.size()) {
			return true;
		} else {
			return false;
		}
	}

	/*
	 * @return String representation of an event on the Timeline.
	 */
	public String next() throws IndexOutOfBoundsException {
		// TODO Auto-generated method stub
		return MainTimeline.get(currentPosition++);
	}
	/*
	 * @return List<String> representation of the main Timeline in the graph.
	 */
	public List<String> getMainTimeline() {
		return MainTimeline;
	}
	/*
	 * @return ArrayList<List<String> an ArrayList containing the Timelines belonging to the subordinating subgraphs
	 */
	public ArrayList<List<String>> getSubordinationTimelines(){
		return SubordinationTimelines;
	}
	/*
	 * @return int number of the amount of timepoints.
	 */
	public int getTotalTimePoints() {

		return totalTimepoints;
	}
	/*
	 * @return List<String> a List containing the breaking points from the Partitioning.java class
	 */
	public List<String> getAttachmentPoints() {
		return attachmentPoints;
	}
	/*
	 * @return String the first timepoint in the Timeline
	 */
	public String getFirstPoint() {
		return MainTimeline.get(0);
	}
	/*
	 * @return String the last timepoint in the Timeline
	 */
	public String getLastPoint() {
		return MainTimeline.get(MainTimeline.size() - 1);
	}
	/*
	 * @return int the number of events in the timeline
	 */
	public int getTimelineLength() {
		//split the last time point in edge/number
		String[] time_point = MainTimeline.get(MainTimeline.size() - 1).split(" = ");
		return Integer.parseInt(time_point[1]);
	}
	/*
	 * @return int the total number of subordination branches in the graph
	 */
	public int getTotalSubordinationBranches() {
		return SubordinationTimelines.size();
	}
	/*
	 * Helper method to initialize the main timeline variable
	 */
	private void initializeMainTimeline() {
		MainTimeline = Timelines.get(0);
		for (List<String> list : Timelines) {
			if (list.size() > MainTimeline.size()) {
				MainTimeline = list;
			}
		}
		Timelines.remove(MainTimeline);
	}
	/*
	 *  Helper method to initialize the subordination timelines
	 */
	private void initializeSubordinationTimelines() {
		if(!Timelines.isEmpty()) {
			for (List<String> list : Timelines) {
				SubordinationTimelines.add(list);
			}
		}
	}
	/*
	 * Helper method to initialize the attachment points
	 */
	private void initializeAttachmentPoints() {
		attachmentPoints = new ArrayList<String>();
		if(!singleSlinks.isEmpty()) {
			for(ILink link : singleSlinks) {
				attachmentPoints.add(link.getEventInstance().getIdStr()+"->"+link.getRelatedToEvent().getIdStr());
			}
		}
	}
	/*
	 * Helper method to count the number of timepoints
	 */
	private void countTimepoints() {
		for (List<String> list : Timelines) {
			this.totalTimepoints += list.size();
		}
	}
		
	
}
