// Path: app/src/main/java/org/hexpresso/elm327/io/Service.java
// public abstract class Service {
// 
//     // TODO handle high level service here, then we can have 2 ELM327 flavors : Bluetooth and WiFi
// 
//     private ServiceStateListener mServiceStateListener = null;
// 
//     private Protocol mProtocol = null;
// 
//     private ServiceStates mState = ServiceStates.STATE_DISCONNECTED;
//     protected InputStream mInputStream = null;
//     protected OutputStream mOutputStream = null;
// 
//     /**
//      * Constructor
//      */
//     protected Service() {
//     }
// 
//     public interface ServiceStateListener {
//         void onServiceStateChanged(ServiceStates state);
//     }
// 
//     /**
//      * Connects to the ELM327 device
//      */
//     public abstract void connect();
// 
//     /**
//      * Disconnects from the ELM327 device
//      */
//     public abstract void disconnect();
// 
//     /**
//      * Returns the current Service state
//      *
//      * @return current Service state.
//      */
//     public synchronized ServiceStates getState() {
//         return mState;
//     }
// 
//     /**
//      * Updates the Service state to the specified state. If a ServiceStateListener is available, it
//      * will be notified.
//      *
//      * @param state new Service state to be set
//      */
//     protected synchronized void setState(final ServiceStates state) {
//         mState = state;
// 
//         // Notify the listeners, if any
//         if( mServiceStateListener != null) {
//             Thread notificationThread = new Thread(new Runnable() {
//                 @Override
//                 public void run() {
//                     mServiceStateListener.onServiceStateChanged(state);
//                 }
//             });
//             notificationThread.start();
//         }
//     }
// 
//     /**
//      * Close the input and output streams if open
//      */
//     protected void closeStreams() {
//         if(mInputStream != null) {
//             try {
//                 mInputStream.close();
//             } catch (IOException e) {
//             }
//         }
// 
//         if(mOutputStream != null) {
//             try {
//                 mOutputStream.close();
//             } catch (IOException e) {
//             }
//         }
//     }
// 
//     protected void startProtocol() {
//         // TODO verify streams not null
//         if(mState == ServiceStates.STATE_CONNECTED) {
//             mProtocol = new Protocol();
//             mProtocol.start(mInputStream, mOutputStream);
//         }
//     }
// 
//     protected void stopProtocol() {
//         if(mProtocol != null) {
//             mProtocol.stop();
//         }
//     }
// 
//     Protocol getProtocol() {
//         return mProtocol;
//     }
// 
//     public void setServiceStateListener(ServiceStateListener listener) {
//         mServiceStateListener = listener;
//     }
// }
// 
// Path: app/src/main/java/org/hexpresso/elm327/io/ServiceStates.java
// public enum ServiceStates {
//     /**
//      * The service is in connecting state
//      */
//     STATE_CONNECTING,
// 
//     /**
//      * The service is in connected state
//      */
//     STATE_CONNECTED,
// 
//     /**
//      * The service is in disconnecting state
//      */
//     STATE_DISCONNECTING,
// 
//     /**
//      * The service is in disconnected state
//      */
//     STATE_DISCONNECTED
// }


import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import org.hexpresso.elm327.io.Service;
import org.hexpresso.elm327.io.ServiceStates;
import java.io.IOException;
import java.util.UUID;

package org.hexpresso.elm327.io.bluetooth;




/**
 * Created by Pierre-Etienne Messier <pierre.etienne.messier@gmail.com> on 2015-10-30.
 */
public class BluetoothService extends Service {

    // We are connecting to a Bluetooth serial board, therefore we use the well-known SPP UUID
    private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    private final BluetoothAdapter mBluetoothAdapter;
    private BluetoothDevice mBluetoothDevice = null;
    private BluetoothSocket mBluetoothSocket = null;

    private boolean mUseSecureConnection = true;
    private Boolean mBluetoothAvailable = null;

    /**
     * Constructor
     */
    public BluetoothService() {
        super();

        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    }

    /**
     * Sets the Bluetooth address of the device to use for connection
     *
     * @param address Device Bluetooth address as string
     */
    public void setDevice(String address) {
        mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(address);
    }

    /**
     * Connects to the ELM327 device
     */
    @Override
    public synchronized void connect() {
        // TODO prevent dual connect?
        if(isBluetoothAvailable()) {
            Thread connectionThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    // Make sure we are disconnected first
                    internalDisconnect();

                    // Start the connection routine
                    internalConnect();
                }
            });
            connectionThread.start();
        }
    }

    /**
     * Connection routine
     */
    private void internalConnect() {

// Path: app/src/main/java/org/hexpresso/elm327/io/Service.java
// public abstract class Service {
// 
//     // TODO handle high level service here, then we can have 2 ELM327 flavors : Bluetooth and WiFi
// 
//     private ServiceStateListener mServiceStateListener = null;
// 
//     private Protocol mProtocol = null;
// 
//     private ServiceStates mState = ServiceStates.STATE_DISCONNECTED;
//     protected InputStream mInputStream = null;
//     protected OutputStream mOutputStream = null;
// 
//     /**
//      * Constructor
//      */
//     protected Service() {
//     }
// 
//     public interface ServiceStateListener {
//         void onServiceStateChanged(ServiceStates state);
//     }
// 
//     /**
//      * Connects to the ELM327 device
//      */
//     public abstract void connect();
// 
//     /**
//      * Disconnects from the ELM327 device
//      */
//     public abstract void disconnect();
// 
//     /**
//      * Returns the current Service state
//      *
//      * @return current Service state.
//      */
//     public synchronized ServiceStates getState() {
//         return mState;
//     }
// 
//     /**
//      * Updates the Service state to the specified state. If a ServiceStateListener is available, it
//      * will be notified.
//      *
//      * @param state new Service state to be set
//      */
//     protected synchronized void setState(final ServiceStates state) {
//         mState = state;
// 
//         // Notify the listeners, if any
//         if( mServiceStateListener != null) {
//             Thread notificationThread = new Thread(new Runnable() {
//                 @Override
//                 public void run() {
//                     mServiceStateListener.onServiceStateChanged(state);
//                 }
//             });
//             notificationThread.start();
//         }
//     }
// 
//     /**
//      * Close the input and output streams if open
//      */
//     protected void closeStreams() {
//         if(mInputStream != null) {
//             try {
//                 mInputStream.close();
//             } catch (IOException e) {
//             }
//         }
// 
//         if(mOutputStream != null) {
//             try {
//                 mOutputStream.close();
//             } catch (IOException e) {
//             }
//         }
//     }
// 
//     protected void startProtocol() {
//         // TODO verify streams not null
//         if(mState == ServiceStates.STATE_CONNECTED) {
//             mProtocol = new Protocol();
//             mProtocol.start(mInputStream, mOutputStream);
//         }
//     }
// 
//     protected void stopProtocol() {
//         if(mProtocol != null) {
//             mProtocol.stop();
//         }
//     }
// 
//     Protocol getProtocol() {
//         return mProtocol;
//     }
// 
//     public void setServiceStateListener(ServiceStateListener listener) {
//         mServiceStateListener = listener;
//     }
// }
// 
// Path: app/src/main/java/org/hexpresso/elm327/io/ServiceStates.java
// public enum ServiceStates {
//     /**
//      * The service is in connecting state
//      */
//     STATE_CONNECTING,
// 
//     /**
//      * The service is in connected state
//      */
//     STATE_CONNECTED,
// 
//     /**
//      * The service is in disconnecting state
//      */
//     STATE_DISCONNECTING,
// 
//     /**
//      * The service is in disconnected state
//      */
//     STATE_DISCONNECTED
// }


// Path: app/src/main/java/org/hexpresso/elm327/io/bluetooth/BluetoothService.java
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import org.hexpresso.elm327.io.Service;
import org.hexpresso.elm327.io.ServiceStates;
import java.io.IOException;
import java.util.UUID;

package org.hexpresso.elm327.io.bluetooth;




/**
 * Created by Pierre-Etienne Messier <pierre.etienne.messier@gmail.com> on 2015-10-30.
 */
public class BluetoothService extends Service {

    // We are connecting to a Bluetooth serial board, therefore we use the well-known SPP UUID
    private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    private final BluetoothAdapter mBluetoothAdapter;
    private BluetoothDevice mBluetoothDevice = null;
    private BluetoothSocket mBluetoothSocket = null;

    private boolean mUseSecureConnection = true;
    private Boolean mBluetoothAvailable = null;

    /**
     * Constructor
     */
    public BluetoothService() {
        super();

        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    }

    /**
     * Sets the Bluetooth address of the device to use for connection
     *
     * @param address Device Bluetooth address as string
     */
    public void setDevice(String address) {
        mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(address);
    }

    /**
     * Connects to the ELM327 device
     */
    @Override
    public synchronized void connect() {
        // TODO prevent dual connect?
        if(isBluetoothAvailable()) {
            Thread connectionThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    // Make sure we are disconnected first
                    internalDisconnect();

                    // Start the connection routine
                    internalConnect();
                }
            });
            connectionThread.start();
        }
    }

    /**
     * Connection routine
     */
    private void internalConnect() {

        setState(ServiceStates.STATE_CONNECTING);
