package com.sogilis.ReactNativeBluetooth.events;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.util.Log;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import static com.sogilis.ReactNativeBluetooth.Constants.MODULE_NAME;

public class EventEmitter {
    private final ReactApplicationContext reactContext;

    public EventEmitter(ReactApplicationContext reactContext) {
        this.reactContext = reactContext;
    }

    public void emit(String eventName, BluetoothDevice device) {
        WritableMap deviceMap = new WritableNativeMap();

        deviceMap.putString("id", device.getAddress());
        deviceMap.putString("address", device.getAddress());
        deviceMap.putString("name", device.getName());

        emit(eventName, deviceMap);
    }

    public void emit(String eventName, BluetoothDevice device, BluetoothGattService service) {
        WritableMap serviceMap = new WritableNativeMap();

        serviceMap.putString("id", service.getUuid().toString());
        serviceMap.putString("deviceId", device.getAddress());

        emit(eventName, serviceMap);
    }

    public void emit(String eventName, BluetoothDevice device, BluetoothGattService service, BluetoothGattCharacteristic characteristic) {
        WritableMap characteristicMap = new WritableNativeMap();

        characteristicMap.putString("id", characteristic.getUuid().toString());
        characteristicMap.putString("serviceId", service.getUuid().toString());
        characteristicMap.putString("deviceId", device.getAddress());

        emit(eventName, characteristicMap);
    }

    public void emit(String eventName, Object eventData) {
        reactContext.
                getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).
                emit(eventName, eventData);
    }

    public void emit(String eventName) {
        logEvent(eventName, null);
        emit(eventName, (Object) null);
    }

    public void emit(String eventName, ReadableMap eventMap) {
        logEvent(eventName, eventMap);
        emit(eventName, (Object) eventMap);
    }

    private void logEvent(String eventName, ReadableMap eventMap) {
        String shortEventName = eventName.substring(eventName.lastIndexOf(".") + 1);

        if (eventMap == null) {
            Log.d(MODULE_NAME, shortEventName);
        } else if (eventMap.hasKey("error")) {
            Log.e(MODULE_NAME, shortEventName + ": " + eventMap.getString("error"));
        } else {
            Log.d(MODULE_NAME, shortEventName + ": " + eventMap.toString());
        }
    }

    public void emitError(String eventName, String errorMessage) {
        WritableMap errorMap = new WritableNativeMap();
        errorMap.putString("error", errorMessage);
        emit(eventName, errorMap);
    }

}

@@ -740,32 +740,400 @@
 Context;%0A    %7D%0A%0A
+    public void emit(String eventName) %7B%0A        logEvent(eventName, null);%0A        jsEmit(eventName, null);%0A    %7D%0A%0A    public void emit(String eventName, String eventData) %7B%0A        String shortEventName = eventName.substring(eventName.lastIndexOf(%22.%22) + 1);%0A        Log.d(MODULE_NAME, shortEventName + %22: %22 + eventData);%0A        jsEmit(eventName, eventData);%0A    %7D%0A%0A
     public void 
@@ -1416,32 +1416,35 @@
 );%0A%0A        emit
+Map
 (eventName, devi
@@ -1746,32 +1746,35 @@
 );%0A%0A        emit
+Map
 (eventName, serv
@@ -2229,32 +2229,35 @@
 );%0A%0A        emit
+Map
 (eventName, char
@@ -2291,32 +2291,37 @@
 public void emit
+Error
 (String eventNam
@@ -2327,145 +2327,146 @@
 me, 
-Object eventData) %7B%0A        reactContext.%0A                getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).%0A    
+String errorMessage) %7B%0A        WritableMap errorMap = new WritableNativeMap();%0A        errorMap.putString(%22error%22, errorMessage);%0A
         
     
@@ -2457,32 +2457,31 @@
 e);%0A        
-    
 emit
+Map
 (eventName, 
@@ -2477,32 +2477,31 @@
 eventName, e
-ventData
+rrorMap
 );%0A    %7D%0A%0A  
@@ -2510,32 +2510,35 @@
 public void emit
+Map
 (String eventNam
@@ -2530,32 +2530,54 @@
 String eventName
+, ReadableMap eventMap
 ) %7B%0A        logE
@@ -2584,36 +2584,40 @@
 vent(eventName, 
-null
+eventMap
 );%0A        emit(
@@ -2603,33 +2603,35 @@
 ntMap);%0A        
-e
+jsE
 mit(eventName, (
@@ -2633,21 +2633,16 @@
 me, 
-(Object) null
+eventMap
 );%0A 
@@ -2648,36 +2648,39 @@
     %7D%0A%0A    p
-ublic
+rivate
  void 
-e
+jsE
 mit(String e
@@ -2689,36 +2689,32 @@
 ntName, 
-ReadableMap
+Object
  event
-Map
+Data
 ) %7B%0A    
@@ -2721,39 +2721,113 @@
     
-logEvent(eventName, eventMap);%0A
+reactContext.%0A                getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).%0A        
     
@@ -2849,26 +2849,18 @@
 ame,
- (Object)
  event
-Map
+Data
 );%0A 
@@ -3345,223 +3345,6 @@
   %7D%0A
-%0A    public void emitError(String eventName, String errorMessage) %7B%0A        WritableMap errorMap = new WritableNativeMap();%0A        errorMap.putString(%22error%22, errorMessage);%0A        emit(eventName, errorMap);%0A    %7D%0A%0A
 %7D%0A

Make sure emit() cannot be called with arbitrary object anymore