package com.openxc;

import java.io.File;

import java.lang.InterruptedException;

import org.apache.commons.io.FileUtils;

import com.openxc.measurements.NoValueException;
import com.openxc.measurements.SteeringWheelAngle;
import com.openxc.measurements.VehicleMeasurement;
import com.openxc.measurements.VehicleSpeed;
import com.openxc.measurements.UnrecognizedMeasurementTypeException;

import com.openxc.remote.RemoteVehicleService;

import com.openxc.remote.sources.TraceVehicleDataSource;

import com.openxc.VehicleService;

import android.content.Intent;

import android.os.RemoteException;

import android.test.ServiceTestCase;

import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;

public class BoundVehicleServiceTest extends ServiceTestCase<VehicleService> {
    VehicleService service;
    VehicleSpeed.Listener speedListener = new VehicleSpeed.Listener() {
        public void receive(VehicleMeasurement measurement) {
            VehicleSpeed speedMeasurement = (VehicleSpeed) measurement;
            assertTrue(false);
        }
    };
    SteeringWheelAngle.Listener steeringWheelListener =
            new SteeringWheelAngle.Listener() {
        public void receive(VehicleMeasurement measurement) {
            SteeringWheelAngle angelMeasurement =
                (SteeringWheelAngle) measurement;
            assertTrue(false);
        }
    };

    public BoundVehicleServiceTest() {
        super(VehicleService.class);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        Intent startIntent = new Intent();
        startIntent.setClass(getContext(), VehicleService.class);
        startIntent.putExtra(RemoteVehicleService.DATA_SOURCE_NAME_EXTRA,
                TraceVehicleDataSource.class.getName());
        FileUtils.copyInputStreamToFile(getContext().getResources().openRawResource(
                    R.raw.tracejson), new File("/data/data/com.openxc/trace.json"));
        startIntent.putExtra(RemoteVehicleService.DATA_SOURCE_RESOURCE_EXTRA,
                "file:///data/data/com.openxc/trace.json");
        service = ((VehicleService.VehicleServiceBinder)
                bindService(startIntent)).getService();
        // sleep for a moment to wait for the vehicle service to bind to the
        // remote service
        try  {
            Thread.sleep(100);
        } catch(InterruptedException e) {
        }
    }

    @SmallTest
    public void testPreconditions() {
    }

    @MediumTest
    public void testGetNoData() throws UnrecognizedMeasurementTypeException {
        VehicleMeasurement measurement = service.get(SteeringWheelAngle.class);
        assertNotNull(measurement);
        assertFalse(measurement.hasValue());
    }

    @MediumTest
    public void testGetMocked() throws UnrecognizedMeasurementTypeException,
            NoValueException, RemoteException, InterruptedException {
        VehicleSpeed measurement = (VehicleSpeed)
                service.get(VehicleSpeed.class);
        assertNotNull(measurement);
        assertTrue(measurement.hasValue());
        assertEquals(measurement.getValue().doubleValue(), 42.0);
    }

    @MediumTest
    public void testAddListener() {
        service.addListener(VehicleSpeed.class, speedListener);
        // TODO trigger a callback make sure the listener is called
    }

    @MediumTest
    public void testAddListenerTwice() {
        service.addListener(VehicleSpeed.class, speedListener);
        service.addListener(VehicleSpeed.class, speedListener);
        // TODO trigger a callback make sure the listener is called only once
    }

    @MediumTest
    public void testAddListenersTwoMeasurements() {
        service.addListener(VehicleSpeed.class, speedListener);
        service.addListener(SteeringWheelAngle.class, steeringWheelListener);
        // TODO trigger callbacks for each, make sure they both get it once
    }

    @MediumTest
    public void testRemoveListener() {
        service.addListener(VehicleSpeed.class, speedListener);
        service.removeListener(VehicleSpeed.class, speedListener);
        // TODO test that we don't recive an update
    }

    @MediumTest
    public void testRemoveTwoListeners() {
        service.addListener(VehicleSpeed.class, speedListener);
        service.addListener(SteeringWheelAngle.class, steeringWheelListener);
        service.removeListener(VehicleSpeed.class, speedListener);
        service.removeListener(SteeringWheelAngle.class, speedListener);
        // TODO test that we don't recive an update in either
    }

    @MediumTest
    public void testRemoveWithoutListening() {
        service.removeListener(VehicleSpeed.class, speedListener);
    }

    @MediumTest
    public void testRemoveOneMeasurementListener() {
        service.addListener(VehicleSpeed.class, speedListener);
        service.addListener(SteeringWheelAngle.class, steeringWheelListener);
        service.removeListener(VehicleSpeed.class, speedListener);
        // TODO test that only the steering wheel stil receives an update
    }
}


@@ -849,16 +849,95 @@
 ervice;%0A
+    VehicleSpeed speedReceived;%0A    SteeringWheelAngle steeringAngleReceived;%0A%0A
     Vehi
@@ -1078,40 +1078,23 @@
     
-VehicleSpeed speedMeasurement
+speedReceived
  =
- 
 (Veh
@@ -1121,39 +1121,8 @@
 nt;%0A
-            assertTrue(false);%0A
     
@@ -1316,61 +1316,31 @@
     
-S
+s
 teering
-WheelAngle angelMeasurement =%0A               
+AngleReceived =
  (St
@@ -1374,39 +1374,8 @@
 nt;%0A
-            assertTrue(false);%0A
     
@@ -1550,24 +1550,94 @@
 er.setUp();%0A
+%0A        speedReceived = null;%0A        steeringAngleReceived = null;%0A%0A
         Inte
@@ -2400,157 +2400,242 @@
     
-try  %7B%0A            Thread.sleep(100);
+pause(100);%0A    %7D%0A%0A    @SmallTest%0A    public void testPreconditions() %7B
 %0A    
+%7D%0A%0A
     
-%7D catch(InterruptedException e) %7B%0A        %7D%0A    %7D%0A%0A    @SmallTest%0A    public void testPreconditions() %7B
+private void checkReceivedMeasurement(VehicleMeasurement measurement) %7B%0A        assertNotNull(measurement);%0A        assertTrue(measurement.hasValue());
 %0A   
@@ -3443,337 +3443,48 @@
     
-// TODO trigger a callback make sure the listener is called%0A    %7D%0A%0A    @MediumTest%0A    public void testAddListenerTwice() %7B%0A        service.addListener(VehicleSpeed.class, speedListener);%0A        service.addListener(VehicleSpeed.class, speedListener);%0A        // TODO trigger a callback make sure the listener is called only once
+checkReceivedMeasurement(speedReceived);
 %0A   
@@ -3709,75 +3709,105 @@
     
-// TODO trigger callbacks for each, make sure they both get it once
+checkReceivedMeasurement(speedReceived);%0A        checkReceivedMeasurement(steeringAngleReceived);
 %0A   
@@ -4008,461 +4008,83 @@
     
-// TODO test that we don't recive an update%0A    %7D%0A%0A    @MediumTest%0A    public void testRemoveTwoListeners() %7B%0A        service.addListener(VehicleSpeed.class, speedListener);%0A        service.addListener(SteeringWheelAngle.class, steeringWheelListener);%0A        service.removeListener(VehicleSpeed.class, speedListener);%0A        service.removeListener(SteeringWheelAngle.class, speedListener);%0A        // TODO test that we don't recive an update in either
+speedReceived = null;%0A        pause(50);%0A        assertNull(speedReceived);
 %0A   
@@ -4213,24 +4213,59 @@
 dListener);%0A
+        assertNull(speedReceived);%0A
     %7D%0A%0A    @
@@ -4549,73 +4549,218 @@
     
-// TODO test that only the steering wheel stil receives an update
+speedReceived = null;%0A        pause(50);%0A        assertNull(speedReceived);%0A    %7D%0A%0A    private void pause(int millis) %7B%0A        try %7B%0A            Thread.sleep(millis);%0A        %7D catch(InterruptedException e) %7B%7D
 %0A   

Add failing tests for listeners.