// Path: cepsim-integration/src/main/java/ca/uwo/eng/sel/cepsim/network/CepNetworkEvent.java
// public class CepNetworkEvent implements Comparable<CepNetworkEvent> {
// 
//     private double origTimestamp;
//     private double destTimestamp;
//     private OutputVertex orig;
//     private InputVertex dest;
//     private EventSet eventSet;
// 
//     public CepNetworkEvent(double origTimestamp, OutputVertex orig, double destTimestamp, InputVertex dest,
//                            EventSet eventSet) {
//         this.origTimestamp = origTimestamp;
//         this.destTimestamp = destTimestamp;
//         this.orig = orig;
//         this.dest = dest;
//         this.eventSet = eventSet;
//     }
// 
//     public double getOrigTimestamp() {
//         return origTimestamp;
//     }
// 
//     public OutputVertex getOrig() {
//         return orig;
//     }
// 
//     public double getDestTimestamp() {
//         return destTimestamp;
//     }
// 
//     public InputVertex getDest() {
//         return dest;
//     }
// 
//     public EventSet getEventSet() {
//         return eventSet;
//     }
// 
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         CepNetworkEvent that = (CepNetworkEvent) o;
// 
//         if (Double.compare(that.destTimestamp, destTimestamp) != 0) return false;
//         if (Double.compare(that.origTimestamp, origTimestamp) != 0) return false;
//         if (!dest.equals(that.dest)) return false;
//         if (!orig.equals(that.orig)) return false;
// 
//         return true;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result;
//         long temp;
//         temp = Double.doubleToLongBits(origTimestamp);
//         result = (int) (temp ^ (temp >>> 32));
//         temp = Double.doubleToLongBits(destTimestamp);
//         result = 31 * result + (int) (temp ^ (temp >>> 32));
//         result = 31 * result + orig.hashCode();
//         result = 31 * result + dest.hashCode();
//         return result;
//     }
// 
//     @Override
//     public int compareTo(CepNetworkEvent o) {
//         int ret = Double.compare(this.destTimestamp, o.destTimestamp);
//         if (ret != 0) return ret;
// 
//         ret =  Double.compare(this.origTimestamp, o.origTimestamp);
//         if (ret != 0) return ret;
// 
//         ret = this.orig.compare(o.orig);
//         if (ret != 0) return ret;
// 
//         return this.dest.compare(o.dest);
//     }
// }


import ca.uwo.eng.sel.cepsim.PlacementExecutor;
import ca.uwo.eng.sel.cepsim.history.History;
import ca.uwo.eng.sel.cepsim.history.SimEvent;
import ca.uwo.eng.sel.cepsim.event.EventSet;
import ca.uwo.eng.sel.cepsim.metric.MetricCalculator;
import ca.uwo.eng.sel.cepsim.network.CepNetworkEvent;
import ca.uwo.eng.sel.cepsim.network.NetworkInterface;
import ca.uwo.eng.sel.cepsim.placement.Placement;
import ca.uwo.eng.sel.cepsim.query.EventConsumer;
import ca.uwo.eng.sel.cepsim.query.EventProducer;
import ca.uwo.eng.sel.cepsim.query.Operator;
import ca.uwo.eng.sel.cepsim.query.Vertex;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import scala.collection.JavaConversions;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyDouble;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
        when(placementExecutor.run(anyDouble(), anyDouble(), anyDouble())).thenReturn(new History<SimEvent>());

		// 1st invocation
        CepQueryCloudlet cloudlet = new CepQueryCloudlet(1, placementExecutor, false, calculator);
        cloudlet.updateQuery(80_000_000L, 80, 0, 1);

        verify(placementExecutor).init(0);
		verify(placementExecutor).run(80_000_000L, 0, 1);
		assertEquals(20.0, cloudlet.getEstimatedTimeToFinish(), 0.0001);
		
		
		// 2nd invocation		
        cloudlet.updateQuery(100_000_000L, 180, 80, 1);
		verify(placementExecutor).run(20_000_000L, 80000, 1);
		assertEquals(0.0, cloudlet.getEstimatedTimeToFinish(), 0.0001);
		assertEquals(0, cloudlet.getRemainingCloudletLength());
	}


    @Test
    public void testUpdateCloudletWithEventsReceived() {
        when(placementExecutor.run(anyDouble(), anyDouble(), anyDouble())).thenReturn(new History<SimEvent>());

        CepQueryCloudlet cloudlet = new CepQueryCloudlet(1, placementExecutor, false, calculator);

        // enqueue network events
        EventSet es1 = new EventSet(1000, 1.0, 0.0, Collections.<EventProducer, Object>singletonMap(p1, 1000.0));
        EventSet es2 = new EventSet(2000, 1.0, 0.0, Collections.<EventProducer, Object>singletonMap(p1, 2000.0));
        EventSet es3 = new EventSet(5000, 1.0, 0.0, Collections.<EventProducer, Object>singletonMap(p1, 5000.0));

// Path: cepsim-integration/src/main/java/ca/uwo/eng/sel/cepsim/network/CepNetworkEvent.java
// public class CepNetworkEvent implements Comparable<CepNetworkEvent> {
// 
//     private double origTimestamp;
//     private double destTimestamp;
//     private OutputVertex orig;
//     private InputVertex dest;
//     private EventSet eventSet;
// 
//     public CepNetworkEvent(double origTimestamp, OutputVertex orig, double destTimestamp, InputVertex dest,
//                            EventSet eventSet) {
//         this.origTimestamp = origTimestamp;
//         this.destTimestamp = destTimestamp;
//         this.orig = orig;
//         this.dest = dest;
//         this.eventSet = eventSet;
//     }
// 
//     public double getOrigTimestamp() {
//         return origTimestamp;
//     }
// 
//     public OutputVertex getOrig() {
//         return orig;
//     }
// 
//     public double getDestTimestamp() {
//         return destTimestamp;
//     }
// 
//     public InputVertex getDest() {
//         return dest;
//     }
// 
//     public EventSet getEventSet() {
//         return eventSet;
//     }
// 
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         CepNetworkEvent that = (CepNetworkEvent) o;
// 
//         if (Double.compare(that.destTimestamp, destTimestamp) != 0) return false;
//         if (Double.compare(that.origTimestamp, origTimestamp) != 0) return false;
//         if (!dest.equals(that.dest)) return false;
//         if (!orig.equals(that.orig)) return false;
// 
//         return true;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result;
//         long temp;
//         temp = Double.doubleToLongBits(origTimestamp);
//         result = (int) (temp ^ (temp >>> 32));
//         temp = Double.doubleToLongBits(destTimestamp);
//         result = 31 * result + (int) (temp ^ (temp >>> 32));
//         result = 31 * result + orig.hashCode();
//         result = 31 * result + dest.hashCode();
//         return result;
//     }
// 
//     @Override
//     public int compareTo(CepNetworkEvent o) {
//         int ret = Double.compare(this.destTimestamp, o.destTimestamp);
//         if (ret != 0) return ret;
// 
//         ret =  Double.compare(this.origTimestamp, o.origTimestamp);
//         if (ret != 0) return ret;
// 
//         ret = this.orig.compare(o.orig);
//         if (ret != 0) return ret;
// 
//         return this.dest.compare(o.dest);
//     }
// }


// Path: cepsim-integration/src/test/java/ca/uwo/eng/sel/cepsim/integr/CepQueryCloudletTest.java
import ca.uwo.eng.sel.cepsim.PlacementExecutor;
import ca.uwo.eng.sel.cepsim.history.History;
import ca.uwo.eng.sel.cepsim.history.SimEvent;
import ca.uwo.eng.sel.cepsim.event.EventSet;
import ca.uwo.eng.sel.cepsim.metric.MetricCalculator;
import ca.uwo.eng.sel.cepsim.network.CepNetworkEvent;
import ca.uwo.eng.sel.cepsim.network.NetworkInterface;
import ca.uwo.eng.sel.cepsim.placement.Placement;
import ca.uwo.eng.sel.cepsim.query.EventConsumer;
import ca.uwo.eng.sel.cepsim.query.EventProducer;
import ca.uwo.eng.sel.cepsim.query.Operator;
import ca.uwo.eng.sel.cepsim.query.Vertex;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import scala.collection.JavaConversions;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyDouble;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

        when(placementExecutor.run(anyDouble(), anyDouble(), anyDouble())).thenReturn(new History<SimEvent>());

		// 1st invocation
        CepQueryCloudlet cloudlet = new CepQueryCloudlet(1, placementExecutor, false, calculator);
        cloudlet.updateQuery(80_000_000L, 80, 0, 1);

        verify(placementExecutor).init(0);
		verify(placementExecutor).run(80_000_000L, 0, 1);
		assertEquals(20.0, cloudlet.getEstimatedTimeToFinish(), 0.0001);
		
		
		// 2nd invocation		
        cloudlet.updateQuery(100_000_000L, 180, 80, 1);
		verify(placementExecutor).run(20_000_000L, 80000, 1);
		assertEquals(0.0, cloudlet.getEstimatedTimeToFinish(), 0.0001);
		assertEquals(0, cloudlet.getRemainingCloudletLength());
	}


    @Test
    public void testUpdateCloudletWithEventsReceived() {
        when(placementExecutor.run(anyDouble(), anyDouble(), anyDouble())).thenReturn(new History<SimEvent>());

        CepQueryCloudlet cloudlet = new CepQueryCloudlet(1, placementExecutor, false, calculator);

        // enqueue network events
        EventSet es1 = new EventSet(1000, 1.0, 0.0, Collections.<EventProducer, Object>singletonMap(p1, 1000.0));
        EventSet es2 = new EventSet(2000, 1.0, 0.0, Collections.<EventProducer, Object>singletonMap(p1, 2000.0));
        EventSet es3 = new EventSet(5000, 1.0, 0.0, Collections.<EventProducer, Object>singletonMap(p1, 5000.0));

        CepNetworkEvent net1 = new CepNetworkEvent(1.0, p1, 6.0,  f1, es1);