package edu.fiu.jtlex.data;

import java.util.Set;

import org.jacop.core.IntVar;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

/**
 * 
 * @author ceber003, luisrobaina, emmanuelgarcia
 *  TODO: Correctly formatted Javadocs for methods
 */
public class IndeterminacyDetector {
	private static boolean[] indeterminatePairs = null;
	private static List<IntVar> shortestTimeLine;
	private static Set<Integer> indeterminateIndexes;
	
/*	private static HashMap<> getTimePointsMap(List<IntVar> timeline)
	{
		// Map timeline discrete points to the events at that point.
		HashMap<Integer, List<String>> eventsAt = new HashMap<>();
		// Fill the hashmap with the events that exists at a given point on time line.
		for (IntVar eventTimePoint : timeline) {
			int timePoint = eventTimePoint.value();
			String timePointID = eventTimePoint.id;

			try {
				List<String> events = eventsAt.get(timePoint);
				events.add(timePointID);
			} catch (Exception e) {
				List<String> events = new ArrayList<>();
				events.add(timePointID);
				eventsAt.put(timePoint, events);
			}
		}
	}*/

	public static void detect(IGraph TimeMLGraph) {

		// Temporal constarint satisfaction solver.
		GraphTCSP tcspSolver = new GraphTCSP(TimeMLGraph);
		// Generate shortest solution.
		ArrayList<List<IntVar>> timelines = new ArrayList<>();
		shortestTimeLine = tcspSolver.solve();
		indeterminatePairs = new boolean[shortestTimeLine.size() - 1];
		indeterminateIndexes = new HashSet<>();
		
		//Create a hundred different solutions and store them in a list.
		for(int i = 0; i < 100; i++) {
			tcspSolver = new GraphTCSP(TimeMLGraph);
			List<IntVar> randomTimeLine = tcspSolver.solveRandom();
			timelines.add(randomTimeLine);
		}
		
		for (int i = 0; i < indeterminatePairs.length; i++ ) {
			boolean checklhs = true, checkrhs = true; //check left hand side, check right hand side
			String rhs, lhs; //take the time pairs from the first timeline
			lhs = shortestTimeLine.get(i).id();
			rhs = shortestTimeLine.get(i + 1).id();
			for (List<IntVar> timeline : timelines) {
				if(timeline.get(i).id().compareTo(lhs) != 0) {
					checklhs = false;
					indeterminateIndexes.add(i);
				}
				if(timeline.get(i+1).id().compareTo(rhs) != 0) {
					checkrhs = false;
					indeterminateIndexes.add(i+1);
				}
			}
			if (!checklhs && !checkrhs) {
				indeterminatePairs[i] = true;
				/*
				 * The pair is marked as indeterminate at this particular index. This tells us that the pair i & i + 1 are indeterminate. 
				 * 
				 * */
			}

		}
	
	}

	// returns a percent value representing the indeterminacy score.
	public static double getIndeterminacyScore() {
		if(indeterminatePairs == null) {
			System.out.println("Please detect indeterminate time points first.");
			return 0.0;
		} else {
			double indeterminatePairCount = 0;
			for (int i = 0; i < indeterminatePairs.length; i++) {
				if(indeterminatePairs[i]) {
					indeterminatePairCount++;
				}
			}
			return indeterminatePairCount/indeterminatePairs.length;
		}
	}

	// returns the adjacent indeterminant time pairings.
	public static List<String> indeterminantTimePairs() {
		List<String> indeterminatePairsList = new ArrayList<>();
		if(indeterminatePairs == null) {
			System.out.println("Please detect indeterminate time points first.");
			return null;
		} else {
			for (int i = 0; i < indeterminatePairs.length; i++) {
				if(indeterminatePairs[i]) {
					indeterminatePairsList.add(shortestTimeLine.get(i).id() + "&" + shortestTimeLine.get(i + 1).id());
				}
			}
			return indeterminatePairsList;
		}
	}

	// returns the time points which are indeterminant.
	public static List<String> indeterminantTimePoints() {
		List<String> indeterminateTimePointsList = new ArrayList<>();
		if(indeterminatePairs == null) {
			System.out.println("Please detect indeterminate time points first.");
			return null;
		} else {
			for (int index: indeterminateIndexes) {
				indeterminateTimePointsList.add(shortestTimeLine.get(index).id());
			}
			return indeterminateTimePointsList;
		}
	}

	// returns the total number of indeterminant time points which have been located
	// by the method.
	public static int getTotalIndeterminantSections() {
		if(indeterminatePairs == null) {
			System.out.println("Please detect indeterminate time points first.");
			return 0;
		} else {
			return indeterminateIndexes.size();
		}
	}

	// returns the overall length of the timeline.
	public static int getTimelineLength() {
		if(indeterminatePairs == null) {
			System.out.println("Please detect indeterminate time points first.");
			return 0;
		} else {
			return shortestTimeLine.size();
		}
	}

	// returns the number of adjacent pairs which have been located by the method.
	public static int getTotalAdjacentPairs() {
		if(indeterminatePairs == null) {
			System.out.println("Please detect indeterminate time points first.");
			return 0;
		} else {
			int adjacentPairs = 0;
			for (int i = 0; i < indeterminatePairs.length; i++) {
				if(indeterminatePairs[i]) {
					adjacentPairs++;
				}
			}
			return adjacentPairs;
		}
	}

}
