package sssj.index;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;

import sssj.base.Vector;

import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterators;

/**
 * A buffer for Vectors. The buffer keeps the order of the vectors as they are added, and maintains the maximum vector. Assumes vectors are added in increasing
 * order of timestamp.
 */
public class VectorWindow {
  private Vector max = new Vector(); // TODO for INVERTED index the max is not needed
  private Queue<Vector> queue = new LinkedList<>();
  private final double tau;
  private int epoch;

  public VectorWindow(double tau) {
    this.tau = tau;
    this.epoch = 0;
  }

  /**
   * Add a vector to the current buffer if the vector timestamp lies within the current buffer window. The vector is defensively copied.
   * 
   * @return true if successfully added the vector, false if the vector timestamp is beyond the current window
   */
  public boolean add(Vector v) {
    Preconditions.checkArgument(v.timestamp() >= windowStart());
    max.updateMaxByDimension(v); // update the max vector
    if (v.timestamp() < windowEnd()) { // v is within the time window of 2*tau
      queue.add(new Vector(v)); // copy constructor needed because the vector iterator reuses its instance
      return true;
    } else {
      return false;
    }
  }

  public Vector getMax() {
    return max;
  }

  public VectorWindow slide() {
    epoch++;
    while (!queue.isEmpty() && queue.peek().timestamp() < windowStart())
      queue.remove();
    // update the max vector
    max.clear();
    for (Vector v : queue)
      max.updateMaxByDimension(v);
    return this;
  }

  public double windowStart() {
    return epoch * tau;
  }

  public double windowEnd() {
    return (epoch + 2) * tau;
  }

  public double windowMid() {
    return (epoch + 1) * tau;
  }

  public int size() {
    return queue.size();
  }

  public Iterator<Vector> firstHalf() {
    return Iterators.filter(queue.iterator(), new Predicate<Vector>() {
      @Override
      public boolean apply(Vector input) {
        return input.timestamp() < windowMid();
      }
    });
  }

  public Iterator<Vector> secondHalf() {
    return Iterators.filter(queue.iterator(), new Predicate<Vector>() {
      @Override
      public boolean apply(Vector input) {
        return input.timestamp() >= windowMid();
      }
    });
  }

  public boolean isEmpty() {
    return this.size() == 0;
  }

  @Override
  public String toString() {
    return "[epoch=" + epoch + ", queue=" + queue + "]";
  }
}

@@ -31,24 +31,26 @@
 va.util.
-Iterator
+ArrayDeque
 ;%0Aimport
@@ -60,26 +60,24 @@
 va.util.
-LinkedList
+Iterator
 ;%0Aimport
@@ -169,93 +169,8 @@
 ons;
-%0Aimport com.google.common.base.Predicate;%0Aimport com.google.common.collect.Iterators;
 %0A%0A/*
@@ -486,44 +486,177 @@
 ate 
-Queue%3CVector%3E queue = new LinkedList
+Vector max2 = new Vector(); // TODO for INVERTED index the max is not needed%0A  private Queue%3CVector%3E q1 = new ArrayDeque%3C%3E();%0A  private Queue%3CVector%3E q2 = new ArrayDeque
 %3C%3E()
@@ -1156,66 +1156,8 @@
 ));%0A
-    max.updateMaxByDimension(v); // update the max vector%0A
     
@@ -1241,33 +1241,63 @@
     
-queue.add(new Vector(v));
+max.updateMaxByDimension(v); // update max vector%0A     
  // 
@@ -1368,16 +1368,242 @@
 nstance%0A
+      if (v.timestamp() %3C windowMid()) %7B%0A        q1.add(new Vector(v));%0A      %7D else %7B%0A        // v.timestamp() %3E= windowMid()%0A        q2.add(new Vector(v));%0A        max2.updateMaxByDimension(v); // update max2 vector%0A      %7D%0A
       re
@@ -1758,95 +1758,96 @@
     
-while (!queue.isEmpty() && queue.peek().timestamp() %3C windowStart())%0A      queue.remove
+// swap the queues%0A    Queue%3CVector%3E tmpq = q1;%0A    q1 = q2;%0A    q2 = tmpq;%0A    q2.clear
 ();%0A
@@ -1853,22 +1853,20 @@
 %0A    // 
-update
+swap
  the max
@@ -1876,85 +1876,81 @@
 ctor
-%0A    max.clear();%0A    for (Vector v : queue)%0A      max.updateMaxByDimension(v
+s%0A    Vector tmpv = max;%0A    max = max2;%0A    max2 = tmpv;%0A    max2.clear(
 );%0A 
@@ -2195,20 +2195,29 @@
 return q
-ueue
+1.size() + q2
 .size();
@@ -2277,431 +2277,92 @@
 urn 
-Iterators.filter(queue.iterator(), new Predicate%3CVector%3E() %7B%0A      @Override%0A      public boolean apply(Vector input) %7B%0A        return input.timestamp() %3C windowMid();%0A      %7D%0A    %7D);%0A  %7D%0A%0A  public Iterator%3CVector%3E secondHalf() %7B%0A    return Iterators.filter(queue.iterator(), new Predicate%3CVector%3E() %7B%0A      @Override%0A      public boolean apply(Vector input) %7B%0A        return input.timestamp() %3E= windowMid();%0A      %7D%0A    %7D
+q1.iterator();%0A  %7D%0A%0A  public Iterator%3CVector%3E secondHalf() %7B%0A    return q2.iterator(
 );%0A 
@@ -2508,22 +2508,31 @@
 %22, q
-ueue
+1=%22 + q1 + %22, q2
 =%22 + q
-ueue
+2
  + %22

Optimize VectorWindow