package com.brickmodule import com.facebook.react.bridge.ReactContext import com.facebook.react.modules.core.DeviceEventManagerModule import java.util.concurrent.ConcurrentHashMap /** * Registry for Brick modules - instance-based approach Each BrickActivity maintains its own * registry instance */ class BrickModuleRegistry { // Simple module storage - no context tracking needed private val modules: ConcurrentHashMap = ConcurrentHashMap() private var isRegistered: Boolean = false /** * Registers an array of Brick modules Each module must implement their respective TypeModule * interface * * @param modules List of module instances to register */ @Synchronized fun register(modules: List) { modules.forEach { module -> registerSingleModule(module) } isRegistered = true println( "โœ… BrickModuleRegistry: Successfully registered ${modules.size} modules (total: ${this.modules.size})" ) } /** * Registers a single module (push-style registration) Useful for manual module registration or * testing * * @param module The module instance to register */ @Synchronized fun push(module: BrickModuleBase) { registerSingleModule(module) println("โœ… BrickModuleRegistry: Module pushed successfully (total: ${modules.size})") } private fun registerSingleModule(module: BrickModuleBase) { val moduleName = module.moduleName if (moduleName.isEmpty()) { println("โŒ BrickModuleRegistry: Module has empty moduleName") return } // Register or update the module val isUpdate = modules.containsKey(moduleName) modules[moduleName] = module if (isUpdate) { println("๐Ÿ”„ BrickModuleRegistry: Module '$moduleName' updated (replaced existing)") } else { println("๐Ÿ“ฆ BrickModuleRegistry: Registered module '$moduleName'") } } /** * Returns the actual module instance for reflection-based method calls Used by BrickModuleImpl * for direct protocol casting * * @param moduleName The name of the module to retrieve */ fun getModuleInstance(moduleName: String): BrickModuleBase? { return modules[moduleName] } /** Returns list of registered module names */ fun getRegisteredModules(): List { return modules.keys.toList().sorted() } /** * Sends an event to JavaScript Used by modules to emit events to JavaScript * * @param context The ReactContext to send the event to * @param eventName The name of the event to send * @param data The event data */ fun sendEvent(context: ReactContext, eventName: String, data: Any?) { try { // Ensure modules are registered if (!isRegistered) { println( "โš ๏ธ BrickModuleRegistry: Modules not registered, skipping event: $eventName" ) return } // Convert data to React Native compatible format using helper val eventData = EventDataConverter.convert(data) println("[BrickModule] sendEvent Context: $context") context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .emit(eventName, eventData) println("๐Ÿ“ก BrickModuleRegistry: Event sent successfully: $eventName") } catch (e: Exception) { println("โŒ BrickModuleRegistry: Failed to send event $eventName: ${e.message}") e.printStackTrace() } } /** Returns all constants from registered modules */ fun getAllConstants(): Map { val allConstants = mutableMapOf() // Create a snapshot to avoid concurrent modification val moduleSnapshot = modules.toMap() moduleSnapshot.forEach { (moduleName, module) -> try { // Get constants directly from BrickModuleBase allConstants[moduleName] = module.getConstants() } catch (e: Exception) { println( "โŒ BrickModuleRegistry: Failed to get constants for $moduleName: ${e.message}" ) } } return allConstants } /** * Unregisters all modules. This should be called when the activity is destroyed to prevent * memory leaks. */ @Synchronized fun unregister() { val count = modules.size // Clear all modules modules.clear() isRegistered = false println("๐Ÿงน BrickModuleRegistry: Unregistered $count modules") } /** Clears all registered modules (for testing purposes only) */ @Synchronized fun clearRegistry() { modules.clear() isRegistered = false println("๐Ÿงน BrickModuleRegistry: Registry cleared") } }