package com.reactnativerfidble

import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.WritableNativeArray
import com.facebook.react.bridge.WritableNativeMap
import com.facebook.react.modules.core.DeviceEventManagerModule
import com.reactnativerfidble.generic.RfidBleGenericEpcReply
import com.reactnativerfidble.generic.RfidBleGenericReader

open class RfidBleEventEmitter(
    private val reactContext: ReactApplicationContext
) {
    companion object {
        private const val EVENT_PREFIX = "RFID_BLE"
    }

    /**
     * RFID_BLE event names
     *
     * This events are mapped directly into TypeScript's code
     */
    enum class RfidEvent {
        DEBUG,

        START_SCANNING,
        STOP_SCANNING,

        READER_RECEIVED,
        READER_CONNECTED,
        READER_DISCONNECTED,

        EPC_REPLIES_READ
    }

    protected fun emitBleEvent(event: RfidEvent, value: Any? = null) {
        val eventEmitter = reactContext
            .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)

        eventEmitter.emit("$EVENT_PREFIX:$event", value)
    }

    fun emitBleDebugEvent(value: Any) {
        emitBleEvent(RfidEvent.DEBUG, value)
    }

    protected fun emitBleReaderEvent(event: RfidEvent, reader: RfidBleGenericReader) {
        val nativeReader = WritableNativeMap()

        nativeReader.putString("name", reader.name ?: "")
        nativeReader.putString("address", reader.address)

        emitBleEvent(event, nativeReader)
    }

    protected fun <T> emitBleEpcReplies(
        device: String,
        replies: List<T>,
        transformer: (reply: T) -> RfidBleGenericEpcReply
    ) {
        val nativeReplies = WritableNativeArray()

        for (reply in replies) {
            val nativeReply = WritableNativeMap()
            val genericReply = transformer(reply)

            nativeReply.putString("device", device)
            nativeReply.putString("epc", genericReply.epc)

            nativeReplies.pushMap(nativeReply)
        }

        emitBleEvent(RfidEvent.EPC_REPLIES_READ, nativeReplies)
    }
}