package com.openxc.remote;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import java.util.HashMap;
import java.util.Map;

import com.openxc.remote.RemoteVehicleServiceListenerInterface;

import com.openxc.remote.sources.VehicleDataSourceCallbackInterface;
import com.openxc.remote.sources.VehicleDataSourceInterface;

import android.app.Service;

import android.content.Intent;

import android.net.Uri;

import android.os.IBinder;
import android.os.RemoteException;

import android.util.Log;

public class RemoteVehicleService extends Service {
    private final static String TAG = "RemoteVehicleService";
    public final static String DATA_SOURCE_NAME_EXTRA = "data_source";
    public final static String DATA_SOURCE_RESOURCE_EXTRA =
            "data_source_resource";

    private Map<String, Double> mNumericalMeasurements;
    private Map<String, String> mStateMeasurements;
    private VehicleDataSourceInterface mDataSource;

    VehicleDataSourceCallbackInterface mCallback =
        new VehicleDataSourceCallbackInterface() {
            public void receive(String name, double value) {
            }

            public void receive(String name, String value) {
            }
        };

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "Service starting");
        mNumericalMeasurements = new HashMap<String, Double>();
        mStateMeasurements = new HashMap<String, String>();
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG, "Service binding in response to " + intent);
        String dataSource = intent.getExtras().getString(
                DATA_SOURCE_NAME_EXTRA);
        String resource = intent.getExtras().getString(
                DATA_SOURCE_RESOURCE_EXTRA);
        initializeDataSource(dataSource, resource);
        return mBinder;
    }

    private void initializeDataSource(String dataSourceName, String resource) {
        Class<? extends VehicleDataSourceInterface> dataSourceType;
        try {
            dataSourceType = Class.forName(dataSourceName).asSubclass(
                    VehicleDataSourceInterface.class);
        } catch(ClassNotFoundException e) {
            Log.w(TAG, "Couldn't find data source type " + dataSourceName, e);
            return;
        }

        Constructor<? extends VehicleDataSourceInterface> constructor;
        try {
            constructor = dataSourceType.getConstructor(
                    VehicleDataSourceCallbackInterface.class, Uri.class);
        } catch(NoSuchMethodException e) {
            Log.d(TAG, dataSourceType + " doesn't have a proper constructor");
            return;
        }

        try {
            mDataSource = constructor.newInstance(mCallback,
                    Uri.parse(resource));
        } catch(InstantiationException e) {
            Log.w(TAG, "Couldn't instantiate data source " + dataSourceType, e);
        } catch(IllegalAccessException e) {
            Log.w(TAG, "Default constructor is not accessible on " +
                    dataSourceType, e);
        } catch(InvocationTargetException e) {
            Log.w(TAG, dataSourceType + "'s constructor threw an exception",
                    e);
        }

        if(mDataSource != null) {
            Log.i(TAG, "Initializing vehicle data source " + mDataSource);
            new Thread(mDataSource).run();
        }
    }

    private final RemoteVehicleServiceInterface.Stub mBinder =
        new RemoteVehicleServiceInterface.Stub() {
            public double getNumericalMeasurement(String measurementId)
                    throws RemoteException {
                return mNumericalMeasurements.get(measurementId).doubleValue();
            }

            public String getStateMeasurement(String measurementId) {
                return mStateMeasurements.get(measurementId);
            }

            public void addListener(
                    RemoteVehicleServiceListenerInterface listener) {
            }

            public void removeListener(
                    RemoteVehicleServiceListenerInterface listener) {
            }
        };
}

@@ -222,24 +222,82 @@
 Interface;%0A%0A
+import com.openxc.remote.sources.ManualVehicleDataSource;%0A
 import com.o
@@ -349,24 +349,24 @@
 kInterface;%0A
-
 import com.o
@@ -501,16 +501,42 @@
 t.Uri;%0A%0A
+import android.os.Bundle;%0A
 import a
@@ -896,16 +896,119 @@
 source%22;
+%0A    private final static String DEFAULT_DATA_SOURCE =%0A        ManualVehicleDataSource.class.getName();
 %0A%0A    pr
@@ -1796,22 +1796,173 @@
         
-String
+Bundle extras = intent.getExtras();%0A        String dataSource = DEFAULT_DATA_SOURCE;%0A        String resource = null;%0A        if(extras != null) %7B%0A           
  dataSou
@@ -1989,32 +1989,36 @@
 as().getString(%0A
+    
                 
@@ -2042,38 +2042,35 @@
 EXTRA);%0A        
-String
+   
  resource = inte
@@ -2103,32 +2103,36 @@
                 
+    
 DATA_SOURCE_RESO
@@ -2136,32 +2136,42 @@
 ESOURCE_EXTRA);%0A
+        %7D%0A
         initiali

Use manual vehicle data source by default.