package misc;

import graph.Graph;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Random;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.TreeSet;

public class Common {
	public static String SEP=",";
	public static final String EXP_DIR = "/home/petko/data/temporal/experiments/";
	
//	public static String RES_DIR="/local/home/student/petko/temporal/figures/";
//	public static String DATA_DIR="/local/home/student/petko/temporal/";
//	public static String TMP_DIR="/local/home/student/petko/temporal/tmp/";
	
	public static String RES_DIR="/home/petko/Dropbox/paper_tgraph/figures/";
	public static String DATA_DIR="/home/petko/data/temporal/";	
	public static String GSEARCH_DATA_DIR="/home/petko/data/gsearch/";
	public static String TMP_DIR="/dev/shm/";
	
	// METIS EXECs and Config
	public static String METIS_EX="/home/petko/Dropbox/bin/pmetis";
	//public static String HMETIS2_EX="/home/petko/bin/hmetis-2/hmetis2.0pre1";
	public static String HMETIS2_EX="/home/petko/Dropbox/bin/hmetis2.0pre1";
	public static String SHMETIS_EX="/home/petko/bin/hmetis-1.5-linux/shmetis";
	public static int HGRAPH_BALLANCE = 5; // int 1-49 imballance percent
	public static String PLOT_DIR="/home/petko/Dropbox/plot/";
	public static double eps = 0.001;
	public static Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("PST"), Locale.US);
	public static DecimalFormat oneDigitFormat = new DecimalFormat("#,##0.0");//format to 1 
	
	public static Random rand = new Random(System.currentTimeMillis());
	
	public static boolean enablePlotting = true;
	
	public static int perc(double frac, double whole) {
		return (int)((frac/whole)*100.0);
	}

	public static int[] estNPoints(long s, long e, int N,
			String samp) {
		int[] res = new int[N];
		TreeMap<Long,Long> samples = new TreeMap<Long, Long>();
		for(String str:samp.split("\t")) 
			samples.put(Long.parseLong(str.split(":")[0]), 
					Long.parseLong(str.split(":")[1]));
		res[0] = samples.firstEntry().getValue().intValue();
		for (int i=1; i < N; i++) {
			long time = ((Double)(s + i*(e-s)*1.0/(N-1))).longValue();
			if (samples.lastEntry().getKey() > time) {
				for (long stime:samples.keySet()) {
					if(stime > time) {
						res[i] = ((Double)linearFit(((Double)(s + (i-1)*(e-s)*1.0/(N-1))).longValue(),
											(long)res[i-1],
											stime,
											samples.get(stime),
											time)).intValue();
						break;
					}
				}
			} else  {
				res[i] = samples.lastEntry().getValue().intValue();
			}
		}
		return res;
	}


	private static double linearFit(long x1, long y1, long x2, long y2, long x) {
		return y1 + (x-x1)*(y2-y1)/(x2-x1);
	}
	
	public static double sum(HashMap<Integer, Double> scores) {
		double res = 0;
		for(Double d:scores.values()) res += d;
		return res;
	}
	
	public static double sum(Collection<Double> scores) {
		double res = 0;
		for(Double d:scores) res += d;
		return res;
	}
	
	public static double sum(double[] scores) {
		double res = 0;
		for(Double d:scores) res += d;
		return res;
	}
	
	public static double l1(double[] a, double[] b) {
		double sum = 0;
		for(int i = 0; i < a.length; i++) 
			sum += Math.abs(a[i] - b[i]);
		return sum;
	}
	
	// intervals
	public static int overlap(int s1, int e1, int s2, int e2) {
		if (s1<s2){
			if(e1<=e2) // s1 s2 e1 e2
				return (e1>=s2)?(e1 - s2 + 1):0;
			else       // s1 s2 e2 e1
				return e2 - s2 + 1;
		}
		else {// s2 <= s1
			if (e2 <= e1) // s2 s1 e2 e1
				return (e2>=s1)?(e2 - s1 +1):0;
			else // s2 s1 e1 e2 
				return e1 -s1 +1;
		}
	}
	
	// vectors
	public static boolean dominates(double[] v, double[] u) {
		for (int i=0;i<v.length; i++) {
			if (u[i]>v[i]) {
				return false;
			}
		}
		return true;
	}
	
	public static double slack_dominates(double[] v, double[] u) {
		double slack = 0.0;
		for (int i=0;i<v.length; i++) {
			if (u[i]>v[i]) {
				slack+= u[i] - v[i];
			}
		}
		return slack;
	}
	
	public static void sum(double[] a, double[] b, double[] res) {
		for(int i = 0; i < a.length; i++) res[i] = a[i] + b[i];
	}
	
	public static double sumPos(double[] a) {
		double sop = 0;
		for(int i = 0; i < a.length; i++) if(a[i] > 0) sop += a[i];
		return sop;
	}
	
	public static float sumPos(float[] a) {
		float sop = 0;
		for(int i = 0; i < a.length; i++) if(a[i] > 0) sop += a[i];
		return sop;
	}
	
	public static int numPos(float[] a) {
		int sop = 0;
		for(int i = 0; i < a.length; i++) if(a[i] > 0) sop += 1;
		return sop;
	}
	
	public static void difference(double[] a, double[] b, double[] res) {
		for(int i = 0; i < a.length; i++) res[i] = a[i] - b[i];
	}
	
	public static void max(double[] a, double[] b, double[] res) {
		for(int i = 0; i < a.length; i++) res[i] = Math.max(a[i], b[i]);
	}
	
	public static float min(float[][] wsl) {
		float res = Float.POSITIVE_INFINITY;
		for (int i=0; i < wsl.length; i++) {
			for (int j = 0 ; j < wsl[i].length; j++) {
				if (res > wsl[i][j]) res = wsl[i][j];
			}
		}
		return res;
	}
	
	public static float max(float[][] wsl) {
		float res = Float.NEGATIVE_INFINITY;
		for (int i=0; i < wsl.length; i++) {
			for (int j = 0 ; j < wsl[i].length; j++) {
				if (res < wsl[i][j]) res = wsl[i][j];
			}
		}
		return res;
	}
	
	public static boolean equals(double[] a, double[] b) {
		for(int i = 0; i < a.length; i++) {
			if (a[i] != b[i]) return false;
		}
		return true;
	}
	
	public static void printArray(double[] v) {
		for (int i=0;i<v.length; i++) {
			System.err.print((int)v[i] + "\t");
		}
		System.err.print("\n");
	}
	
	public static TreeMap<Double, Double> counts(int[] values) {
		 TreeMap<Double, Double> c = new TreeMap<Double, Double>();
		 for (int v:values) {
			 if (!c.containsKey(1.0*v)) c.put(1.0*v, 0.0);
			 c.put(1.0*v, c.get(1.0*v) + 1.0);
		 }
		 return c;
	}
	
	public static TreeMap<Double, Double> counts(double[] values) {
		TreeMap<Double, Double> c = new TreeMap<Double, Double>();
		 for (double v:values) {
			 if (!c.containsKey(1.0*v)) c.put(1.0*v, 0.0);
			 c.put(1.0*v, c.get(1.0*v) + 1.0);
		 }
		 return c;
	}
	
	public static double jc(BitSet a, BitSet b) {
		BitSet u = new BitSet(), in = new BitSet(); 
		u.or(a); u.or(b);
		in.or(a); in.and(b);
		return in.cardinality()*1.0/u.cardinality();
	}
	
	public static double avgNCut(ArrayList<String> p, Graph g) {
		HashMap<String,Double> cut = new HashMap<String,Double>();
		HashMap<String,Double> assoc = new HashMap<String,Double>();
		getClusterStats(p, g, cut, assoc);
		
		double res = 0.0;
		for (String s: cut.keySet()) {
			res += cut.get(s) / assoc.get(s);
		}
		return res;
	}
	
	public static double avgConductance(ArrayList<String> p, Graph g) {
		HashMap<String,Double> cut = new HashMap<String,Double>();
		HashMap<String,Double> assoc = new HashMap<String,Double>();
		getClusterStats(p, g, cut, assoc);
		
		double res = 0.0;
		for (String s: cut.keySet()) {
			double assocrest = 0.0;
			for (String s1: assoc.keySet()) {
				if(!s1.equals(s)) 
					assocrest += assoc.get(s1);
			}
			res += cut.get(s) / Math.min(assoc.get(s),assocrest);
		}
		return res;
	}

	public static void getClusterStats(ArrayList<String> p, Graph g,
			HashMap<String, Double> cut, HashMap<String, Double> assoc) {
		String l1,l2;
		for (int i=0; i < g.getn(); i++) {
			l1 = p.get(i);
			for (int j= g.ind(i); j < g.ind(i+1); j++) {
				l2 = p.get(g.endv(j));
				if(!assoc.containsKey(l1)) assoc.put(l1,0.0);
				assoc.put(l1, assoc.get(l1) + g.we(j)); 
				if(!assoc.containsKey(l2)) assoc.put(l2,0.0);
				assoc.put(l2, assoc.get(l2) + g.we(j)); 
				if (!l1.equals(l2)) {
					if(!cut.containsKey(l1)) cut.put(l1,0.0);
					cut.put(l1, cut.get(l1) + g.we(j)); 
					if(!cut.containsKey(l2)) cut.put(l2,0.0);
					cut.put(l2, cut.get(l2) + g.we(j));
				}
			}
		}
	}
	
	
	
	public static void main(String[] args ) {
		
		int ol = overlap(10,11,5,10);
		double a = linearFit(1, 1, 3, 3, 2);
		int[] est = estNPoints(100, 200, 5, "133:12\t155:22\t180:12");
		int[] est1 = estNPoints(100, 200, 2, "133:12\t155:0\t180:12");
	}

	

	

	

	

	


	


	


	


	


	
}
