// Path: bletia-core/src/main/java/info/izumin/android/bletia/core/BleState.java
// public enum BleState {
//     DISCONNECTED,
//     CONNECTING,
//     CONNECTED,
//     SERVICE_DISCOVERING,
//     SERVICE_DISCOVERED,
//     DISCONNECTING
// }
// 
// Path: rxbletia/src/main/java/info/izumin/android/bletia/rx/RxBletia.java
// public class RxBletia extends AbstractBletia {
//     public static final String TAG = RxBletia.class.getSimpleName();
// 
//     private final Map<UUID, RxEnableNotificationAction> mEnabledNotificationList;
//     private final PublishSubject<BletiaException> mExceptionSubject;
// 
//     public RxBletia(Context context) {
//         super(context);
//         setSubListener(mListener);
//         mEnabledNotificationList = new HashMap<>();
//         mExceptionSubject = PublishSubject.create();
//     }
// 
//     public Observable<Void> connect(BluetoothDevice device) {
//         return execute(new RxConnectAction(device, getStateContainer()));
//     }
// 
//     public Observable<Void> disconnect() {
//         return execute(new RxDisconnectAction(getStateContainer()));
//     }
// 
//     public Observable<Void> discoverServices() {
//         return execute(new RxDiscoverServicesAction(getStateContainer()));
//     }
// 
//     public Observable<BluetoothGattCharacteristic> writeCharacteristic(BluetoothGattCharacteristic characteristic) {
//         return execute(new RxWriteCharacteristicAction(characteristic));
//     }
// 
//     public Observable<BluetoothGattCharacteristic> readCharacteristic(BluetoothGattCharacteristic characteristic) {
//         return execute(new RxReadCharacteristicAction(characteristic));
//     }
// 
//     public Observable<BluetoothGattDescriptor> writeDescriptor(BluetoothGattDescriptor descriptor) {
//         return execute(new RxWriteDescriptorAction(descriptor));
//     }
// 
//     public Observable<BluetoothGattDescriptor> readDescriptor(BluetoothGattDescriptor descriptor) {
//         return execute(new RxReadDescriptorAction(descriptor));
//     }
// 
//     public Observable<BluetoothGattCharacteristic> enableNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
//         return enabled ? enableNotification(characteristic) : disableNotification(characteristic);
//     }
// 
//     public Observable<BluetoothGattCharacteristic> enableNotification(final BluetoothGattCharacteristic characteristic) {
//         final UUID uuid = characteristic.getUuid();
//         if (mEnabledNotificationList.containsKey(uuid)) {
//             return mEnabledNotificationList.get(uuid).getResolver();
//         }
//         final RxEnableNotificationAction action = new RxEnableNotificationAction(characteristic);
//         mEnabledNotificationList.put(characteristic.getUuid(), action);
//         return execute(action).doOnUnsubscribe(new Action0() {
//             @Override
//             public void call() {
//                 mEnabledNotificationList.remove(uuid);
//             }
//         });
//     }
// 
//     public Observable<BluetoothGattCharacteristic> disableNotification(BluetoothGattCharacteristic characteristic) {
//         return execute(new RxDisableNotificationAction(characteristic))
//                 .doOnNext(new Action1<BluetoothGattCharacteristic>() {
//                     @Override
//                     public void call(BluetoothGattCharacteristic characteristic) {
//                         mEnabledNotificationList.remove(characteristic.getUuid());
//                     }
//                 });
//     }
// 
//     public Observable<Integer> readRemoteRssi() {
//         return execute(new RxReadRemoteRssiAction());
//     }
// 
//     public Observable<BletiaException> observeError() {
//         return mExceptionSubject;
//     }
// 
//     private final BleEventListener mListener = new BleEventListener() {
//         @Override
//         public void onCharacteristicChanged(final BluetoothGattCharacteristic characteristic) {
//             final UUID uuid = characteristic.getUuid();
//             if (mEnabledNotificationList.containsKey(uuid)) {
//                 mEnabledNotificationList.get(uuid).resolve(characteristic);
//             }
//         }
// 
//         @Override
//         public void onError(BletiaException exception) {
//             mExceptionSubject.onNext(exception);
//         }
//     };
// }


import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.UUID;
import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.OnItemClick;
import info.izumin.android.bletia.core.BleState;
import info.izumin.android.bletia.rx.RxBletia;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.subscriptions.CompositeSubscription;

    private BluetoothManager mBluetoothManager;
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothLeScanner mScanner;

    private BleDeviceAdapter mDeviceAdapter;

    private Menu mMenu;

    @Bind(R.id.list_devices)
    ListView mDeviceListView;
    @Bind(R.id.main)
    View mMainContent;
    @Bind(R.id.text_battery_level)
    TextView mTextBatteryLevel;
    @Bind(R.id.text_battery_state)
    TextView mTextBatteryState;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        mDeviceAdapter = new BleDeviceAdapter(this);
        mDeviceListView.setAdapter(mDeviceAdapter);

        mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = mBluetoothManager.getAdapter();

// Path: bletia-core/src/main/java/info/izumin/android/bletia/core/BleState.java
// public enum BleState {
//     DISCONNECTED,
//     CONNECTING,
//     CONNECTED,
//     SERVICE_DISCOVERING,
//     SERVICE_DISCOVERED,
//     DISCONNECTING
// }
// 
// Path: rxbletia/src/main/java/info/izumin/android/bletia/rx/RxBletia.java
// public class RxBletia extends AbstractBletia {
//     public static final String TAG = RxBletia.class.getSimpleName();
// 
//     private final Map<UUID, RxEnableNotificationAction> mEnabledNotificationList;
//     private final PublishSubject<BletiaException> mExceptionSubject;
// 
//     public RxBletia(Context context) {
//         super(context);
//         setSubListener(mListener);
//         mEnabledNotificationList = new HashMap<>();
//         mExceptionSubject = PublishSubject.create();
//     }
// 
//     public Observable<Void> connect(BluetoothDevice device) {
//         return execute(new RxConnectAction(device, getStateContainer()));
//     }
// 
//     public Observable<Void> disconnect() {
//         return execute(new RxDisconnectAction(getStateContainer()));
//     }
// 
//     public Observable<Void> discoverServices() {
//         return execute(new RxDiscoverServicesAction(getStateContainer()));
//     }
// 
//     public Observable<BluetoothGattCharacteristic> writeCharacteristic(BluetoothGattCharacteristic characteristic) {
//         return execute(new RxWriteCharacteristicAction(characteristic));
//     }
// 
//     public Observable<BluetoothGattCharacteristic> readCharacteristic(BluetoothGattCharacteristic characteristic) {
//         return execute(new RxReadCharacteristicAction(characteristic));
//     }
// 
//     public Observable<BluetoothGattDescriptor> writeDescriptor(BluetoothGattDescriptor descriptor) {
//         return execute(new RxWriteDescriptorAction(descriptor));
//     }
// 
//     public Observable<BluetoothGattDescriptor> readDescriptor(BluetoothGattDescriptor descriptor) {
//         return execute(new RxReadDescriptorAction(descriptor));
//     }
// 
//     public Observable<BluetoothGattCharacteristic> enableNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
//         return enabled ? enableNotification(characteristic) : disableNotification(characteristic);
//     }
// 
//     public Observable<BluetoothGattCharacteristic> enableNotification(final BluetoothGattCharacteristic characteristic) {
//         final UUID uuid = characteristic.getUuid();
//         if (mEnabledNotificationList.containsKey(uuid)) {
//             return mEnabledNotificationList.get(uuid).getResolver();
//         }
//         final RxEnableNotificationAction action = new RxEnableNotificationAction(characteristic);
//         mEnabledNotificationList.put(characteristic.getUuid(), action);
//         return execute(action).doOnUnsubscribe(new Action0() {
//             @Override
//             public void call() {
//                 mEnabledNotificationList.remove(uuid);
//             }
//         });
//     }
// 
//     public Observable<BluetoothGattCharacteristic> disableNotification(BluetoothGattCharacteristic characteristic) {
//         return execute(new RxDisableNotificationAction(characteristic))
//                 .doOnNext(new Action1<BluetoothGattCharacteristic>() {
//                     @Override
//                     public void call(BluetoothGattCharacteristic characteristic) {
//                         mEnabledNotificationList.remove(characteristic.getUuid());
//                     }
//                 });
//     }
// 
//     public Observable<Integer> readRemoteRssi() {
//         return execute(new RxReadRemoteRssiAction());
//     }
// 
//     public Observable<BletiaException> observeError() {
//         return mExceptionSubject;
//     }
// 
//     private final BleEventListener mListener = new BleEventListener() {
//         @Override
//         public void onCharacteristicChanged(final BluetoothGattCharacteristic characteristic) {
//             final UUID uuid = characteristic.getUuid();
//             if (mEnabledNotificationList.containsKey(uuid)) {
//                 mEnabledNotificationList.get(uuid).resolve(characteristic);
//             }
//         }
// 
//         @Override
//         public void onError(BletiaException exception) {
//             mExceptionSubject.onNext(exception);
//         }
//     };
// }


// Path: samples/rxbletia-sample/src/main/java/info/izumin/android/rx/sample/MainActivity.java
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.UUID;
import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.OnItemClick;
import info.izumin.android.bletia.core.BleState;
import info.izumin.android.bletia.rx.RxBletia;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.subscriptions.CompositeSubscription;


    private BluetoothManager mBluetoothManager;
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothLeScanner mScanner;

    private BleDeviceAdapter mDeviceAdapter;

    private Menu mMenu;

    @Bind(R.id.list_devices)
    ListView mDeviceListView;
    @Bind(R.id.main)
    View mMainContent;
    @Bind(R.id.text_battery_level)
    TextView mTextBatteryLevel;
    @Bind(R.id.text_battery_state)
    TextView mTextBatteryState;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        mDeviceAdapter = new BleDeviceAdapter(this);
        mDeviceListView.setAdapter(mDeviceAdapter);

        mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = mBluetoothManager.getAdapter();

        mBletia = new RxBletia(getApplicationContext());