package smooth;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.BitSet;
import java.util.HashSet;
import java.util.Vector;

import graph.WeightedTimeGraph;

// this is a wrapper for the evonet Upper bound
public class UpperBound {
	
	// TODO: ask Misael to expose a start-end UB computation (allow faster computation)
	public static float[][] ub(WeightedTimeGraph tg, int s, int e) {
		float[][] res = new float[tg.gett()][tg.getm()];
		for (int t = 0; t < tg.gett(); t++) Arrays.fill(res[t], Float.POSITIVE_INFINITY);
		// set the intervals of no interest to surely pruned
		for (int t = 0; t < s; t++) Arrays.fill(res[t], Float.NEGATIVE_INFINITY);
		for (int t = e+1; t < tg.gett(); t++) Arrays.fill(res[t], Float.NEGATIVE_INFINITY);
		return res;
	}
	
	// TODO: ask Misael about whether he stores the indices or names of nodes?
	public static float[][] readUb(String fn, WeightedTimeGraph tg, int s, int e) {
		float[][] res = new float[tg.gett()][tg.getn()];
		
		for (int t = 0; t < tg.gett(); t++) Arrays.fill(res[t], Float.POSITIVE_INFINITY);
		
		// set the intervals of no interest to surely pruned
		for (int t = 0; t < s; t++) Arrays.fill(res[t], Float.NEGATIVE_INFINITY);
		for (int t = e+1; t < tg.gett(); t++) Arrays.fill(res[t], Float.NEGATIVE_INFINITY);
		return res;
	}
	
	public static BitSet[] computeAllowed(WeightedTimeGraph wtg, int s, int e,
			float lb, float[][] ubnds) {
		
		// Compute allowed edges
		BitSet[] allowed = new BitSet[wtg.gett()];
		
		for (int t=s; t <= e; t++) {
			allowed[t] = new BitSet(wtg.getm());
			if (null==ubnds) {allowed[t].set(0,wtg.getm()); continue;}
			for (int i = 0; i < wtg.getn(); i++) {
				if (ubnds[t][i] < lb) continue;
				for (int j = wtg.ind[i]; j < wtg.ind[i+1]; j++) {
					if (ubnds[t][wtg.endv[j]] >= lb) {
						allowed[t].set(j);
					}
				}
			}
		}
		return allowed;
	}

	public static Vector<HashSet<Integer>> readValidNodes(String ubf, double lb, WeightedTimeGraph wtg) throws IOException {
		Vector<HashSet<Integer>> validNodes = new Vector<HashSet<Integer>>();
        validNodes.setSize(wtg.gett());
        for (int slice = 0; slice < wtg.gett(); slice++) {
            validNodes.set(slice,new HashSet<Integer>());
        }
        
        BufferedReader br = new BufferedReader(new FileReader(ubf));
        String line = null;
        // transform node names to node ids!!!!
        while ((line = br.readLine())!=null) {
        	String[] sline = line.split(", ");
        	if (Double.parseDouble(sline[2]) >= lb) {
        		int nodeid = wtg.getNodeIndex(sline[0]);
        		validNodes.get(Integer.parseInt(sline[1])).add(nodeid);
        	}
        }
        return validNodes;
	}

	public static double getPrunedEdgesPercentage(
			Vector<HashSet<Integer>> validNodes, WeightedTimeGraph wtg) {
		double ewp = 0; 
		for (int t=0; t < wtg.gett(); t++) {
			if (validNodes.get(t).size()==0) continue;
			for (int i=0; i < wtg.getn(); i++) {
				for(int j = wtg.ind[i]; j < wtg.ind[i+1]; j++) {
					if (validNodes.get(t).contains(i) && validNodes.get(t).contains(wtg.endv[j])) {
						ewp++;
					}
				}
			}
		}
		return 1.0*ewp/(wtg.gett()*wtg.getm());
	}
	
	
}
