package index;

import graph.TimeGraph;
import java.util.ArrayList;
import misc.Common;

public class IntervalIndex {
	
	private ArrayList<double[][]> pvs;
	private ArrayList<IntervalTreeNode> topnodes;
	
	// computes tlogt vectors : t of size 1, t/2 of size 2 ...
	public IntervalIndex(TimeGraph tg, int s,int e) {
		int size =  e-s+1;
		// compute tlogt vectors
		pvs = new ArrayList<double[][]>();
		topnodes = new ArrayList<IntervalTreeNode>();
		
		ArrayList<IntervalTreeNode> nodes = new ArrayList<IntervalTreeNode>();
		ArrayList<IntervalTreeNode> prevnodes = new ArrayList<IntervalTreeNode>();
		for (int pow = 0; Math.pow(2, pow) < size; pow++) {
			int len = (int)Math.pow(2, pow);
			double[][] vs = new double[size/len + ((size%len > 0)?1:0)][tg.getm()];
			for (int pos = 0; pos + len  <= size; pos += len) {
				if (len == 1) {
					tg.aggregateByTime(s+pos, s+pos+len-1,vs[pos/len]);
					nodes.add(new IntervalTreeNode(pos, pos+len-1,vs[pos/len]));
				}
				else {
					Common.sum(pvs.get(pow-1)[pos/(int)Math.pow(2, pow-1)], 
							 pvs.get(pow-1)[pos/(int)Math.pow(2, pow-1) + 1],
							 vs[pos/len]);
					nodes.add(new IntervalTreeNode(pos, pos+len-1, vs[pos/len]));
					nodes.get(nodes.size()-1).L = prevnodes.get(pos/(int)Math.pow(2, pow-1));
					nodes.get(nodes.size()-1).R = prevnodes.get(pos/(int)Math.pow(2, pow-1) + 1);
				}
			}
			if( (prevnodes.size()%2) > 0) 
				topnodes.add(0, prevnodes.get(prevnodes.size()-1));
			prevnodes.clear();
			prevnodes.addAll(nodes);
			nodes.clear();
			pvs.add(vs);
		}
		topnodes.add(0,prevnodes.get(0));
	}
	
	public void getCeiling(int start_fixed, int end_fixed, int end, double[] v) {
		aggregate(start_fixed,end_fixed,v,false);
		double[] ceil = new double[v.length];
		aggregate(end_fixed+1, end, ceil, true);
		
		Common.sum(v,ceil,v);
	}

	private void aggregate(int s, int e, double[] v, boolean onlyPositive) {
		//System.err.print("***********************\nQuery [" + s + "," + e + "]\n");
		if (s > e) return;
		for (IntervalTreeNode n: topnodes ) {
			n.aggregate(s,e,v,onlyPositive);
		}
	}
}
