package com.reactnativerfidble.adapters

import android.bluetooth.le.ScanResult
import android.os.ParcelUuid
import com.facebook.react.bridge.ReactApplicationContext
import com.reactnativerfidble.RfidBleEventEmitter
import java.lang.Error

abstract class RfidBleAdapter(reactContext: ReactApplicationContext) :
    RfidBleEventEmitter(reactContext) {
    companion object {
        val SUPPORTED_ADAPTERS = SupportedAdapter.values()

        enum class SupportedAdapter(
            val address: String? = null,
            val serviceUuids: List<ParcelUuid> = listOf()
        ) {
            /**
             * Watch - Model: IVF-BU01
             */
            BU01(
                null,
                listOf(
                    ParcelUuid.fromString("0000fee7-0000-1000-8000-00805f9b34fb"),
                    ParcelUuid.fromString("0000ffb0-0000-1000-8000-00805f9b34fb")
                )
            ) {
                override fun getInstance(context: ReactApplicationContext) =
                    RfidBleBU01Adapter(context)
            },

            /**
             * Gun - Model: CF-U909
             */
            U909("D5:2A:A7:55:6C:3A") {
                override fun getInstance(context: ReactApplicationContext) =
                    RfidBleU909Adapter(context)
            },

            /**
             * Portable - Model: CF-H301
             */
            H301(
                null,
                listOf(ParcelUuid.fromString("0000ffe0-0000-1000-8000-00805f9b34fb"))
            ) {
                override fun getInstance(context: ReactApplicationContext) =
                    RfidBleH301Adapter(context)
            };

            abstract fun getInstance(context: ReactApplicationContext): RfidBleAdapter
        }

        fun getAdapterInstance(
            scanResult: ScanResult,
            reactContext: ReactApplicationContext
        ): RfidBleAdapter {
            val supportedAdapters = SupportedAdapter.values()
            val readerDevice = scanResult.device
            val deviceServiceUuids = scanResult.scanRecord?.serviceUuids

            for (supportedAdapter in supportedAdapters) {
                if (supportedAdapter.address != null && supportedAdapter.address == readerDevice.address) {
                    return supportedAdapter.getInstance(reactContext)
                } else if (deviceServiceUuids != null) {
                    for (serviceUuid in supportedAdapter.serviceUuids) {
                        for (deviceUuid in deviceServiceUuids) {
                            if (serviceUuid == deviceUuid) {
                                return supportedAdapter.getInstance(reactContext)
                            }
                        }
                    }
                }
            }

            throw Error("Unimplemented adapter for reader with address: ${readerDevice.address}")
        }
    }

    /**
     * Connects to given reader's address
     */
    abstract fun connectToReader(readerAddress: String)

    /**
     * Disconnects from current connected reader
     */
    abstract fun disconnect()
}
