package info.izumin.android.bletia;

import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;

import info.izumin.android.bletia.wrapper.BluetoothGattCallbackWrapper;
import info.izumin.android.bletia.wrapper.BluetoothGattWrapper;

/**
 * Created by izumin on 9/7/15.
 */
public class BluetoothGattCallbackHandler extends BluetoothGattCallbackWrapper {

    private Callback mCallback;
    private BleEventStore mEventStore;

    public BluetoothGattCallbackHandler(Callback callback, BleEventStore eventStore) {
        mCallback = callback;
        mEventStore = eventStore;
    }

    @Override
    public void onConnectionStateChange(BluetoothGattWrapper gatt, int status, int newState) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            if (newState == BluetoothGatt.STATE_CONNECTED) {
                mCallback.onConnect(gatt);
            }
            if (newState == BluetoothGatt.STATE_DISCONNECTED) {
                mCallback.onDisconnect(gatt);
            }
        } else {
            mCallback.onError(new BletiaException(BleErrorType.valueOf(status)));
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGattWrapper gatt, int status) {
        // TODO: Not yet implemented.
    }

    @Override
    public void onCharacteristicRead(BluetoothGattWrapper gatt, BluetoothGattCharacteristic characteristic, int status) {
        handleBleEvent(BleEvent.Type.READ_CHARACTERISTIC, characteristic, status);
    }

    @Override
    public void onCharacteristicWrite(BluetoothGattWrapper gatt, BluetoothGattCharacteristic characteristic, int status) {
        handleBleEvent(BleEvent.Type.WRITE_CHARACTERISTIC, characteristic, status);
    }

    @Override
    public void onCharacteristicChanged(BluetoothGattWrapper gatt, BluetoothGattCharacteristic characteristic) {
        // TODO: Not yet implemented.
    }

    @Override
    public void onDescriptorRead(BluetoothGattWrapper gatt, BluetoothGattDescriptor descriptor, int status) {
        handleBleEvent(BleEvent.Type.READ_DESCRIPTOR, descriptor, status);
    }

    @Override
    public void onDescriptorWrite(BluetoothGattWrapper gatt, BluetoothGattDescriptor descriptor, int status) {
        handleBleEvent(BleEvent.Type.WRITE_DESCRIPTOR, descriptor, status);
    }

    @Override
    public void onReliableWriteCompleted(BluetoothGattWrapper gatt, int status) {
        // TODO: Not yet implemented.
    }

    @Override
    public void onReadRemoteRssi(BluetoothGattWrapper gatt, int rssi, int status) {
        // TODO: Not yet implemented.
    }

    @Override
    public void onMtuChanged(BluetoothGattWrapper gatt, int mtu, int status) {
        // TODO: Not yet implemented.
    }

    private void handleBleEvent(BleEvent.Type type, BluetoothGattCharacteristic characteristic, int status) {
        BleEvent<BluetoothGattCharacteristic> event = mEventStore.closeEvent(type, characteristic.getUuid());
        if (status == BluetoothGatt.GATT_SUCCESS) {
            event.getDeferred().resolve(event.getValue());
        } else {
            event.getDeferred().reject(new BletiaException(BleErrorType.valueOf(status), characteristic));
        }
    }

    private void handleBleEvent(BleEvent.Type type, BluetoothGattDescriptor descriptor, int status) {
        BleEvent<BluetoothGattDescriptor> event = mEventStore.closeEvent(type, descriptor.getUuid());
        if (status == BluetoothGatt.GATT_SUCCESS) {
            event.getDeferred().resolve(descriptor);
        } else {
            event.getDeferred().reject(new BletiaException(BleErrorType.valueOf(status), descriptor));
        }
    }

    interface Callback {
        void onConnect(BluetoothGattWrapper gatt);
        void onDisconnect(BluetoothGattWrapper gatt);
        void onError(BletiaException exception);
    }
}

@@ -175,16 +175,100 @@
 iptor;%0A%0A
+import java.util.Arrays;%0A%0Aimport info.izumin.android.bletia.util.NotificationUtils;%0A
 import i
@@ -2353,32 +2353,444 @@
 , int status) %7B%0A
+        if (NotificationUtils.isEnableNotificationDescriptor(descriptor)) %7B%0A            handleBleEvent(BleEvent.Type.ENABLE_NOTIFICATION, descriptor.getCharacteristic(), descriptor, status);%0A        %7D else if (NotificationUtils.isDisableNotificationDescriptor(descriptor)) %7B%0A            handleBleEvent(BleEvent.Type.DISABLE_NOTIFICATION, descriptor.getCharacteristic(), descriptor, status);%0A        %7D else %7B%0A    
         handleBl
@@ -2841,32 +2841,42 @@
 iptor, status);%0A
+        %7D%0A
     %7D%0A%0A    @Over
@@ -3324,34 +3324,30 @@
 ent(BleEvent
-.Type type
+ event
 , BluetoothG
@@ -3384,131 +3384,57 @@
 ic, 
-int status) %7B%0A        BleEvent%3CBluetoothGattCharacteristic%3E event = mEventStore.closeEvent(type, characteristic.getUuid());
+BluetoothGattDescriptor descriptor, int status) %7B
 %0A   
@@ -3661,16 +3661,28 @@
 teristic
+, descriptor
 ));%0A    
@@ -3745,16 +3745,60 @@
 pe type,
+ BluetoothGattCharacteristic characteristic,
  Bluetoo
@@ -3870,26 +3870,30 @@
 oothGatt
-Descriptor
+Characteristic
 %3E event 
@@ -3923,26 +3923,30 @@
 t(type, 
-descriptor
+characteristic
 .getUuid
@@ -3962,209 +3962,541 @@
     
-if (status == BluetoothGatt.GATT_SUCCESS) %7B%0A            event.getDeferred().resolve(descriptor);%0A        %7D else %7B%0A  
+handleBleEvent(event, characteristic, descriptor, status);%0A    %7D%0A%0A    private void handleBleEvent(BleEvent.Type type, BluetoothGattCharacteristic characteristic, int status) %7B%0A        BleEvent%3CBluetoothGattCharacteristic%3E event = mEventStore.closeEvent(type, characteristic.getUuid());%0A        handleBleEvent(event, characteristic, null, status);%0A
     
+%7D%0A%0A
     
-  event.getDeferred().reject(new BletiaException(BleErrorType.valueOf(status)
+private void handleBleEvent(BleEvent.Type type, BluetoothGattDescriptor descriptor, int status) %7B%0A        BleEvent%3CBluetoothGattDescriptor%3E event = mEventStore.closeEvent(type
 , de
@@ -4495,32 +4495,41 @@
 type, descriptor
+.getUuid(
 ));%0A        %7D%0A  
@@ -4516,33 +4516,80 @@
 uid());%0A        
-%7D
+handleBleEvent(event, null, descriptor, status);
 %0A    %7D%0A%0A    inte

Make handlable notification event callback