package com.geeksville.mesh.model import androidx.lifecycle.Lifecycle import androidx.lifecycle.coroutineScope import com.geeksville.mesh.MyNodeInfo import com.geeksville.mesh.NodeInfo import com.geeksville.mesh.database.dao.NodeInfoDao import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.withContext import javax.inject.Inject import javax.inject.Singleton @Singleton class NodeDB @Inject constructor( processLifecycle: Lifecycle, private val nodeInfoDao: NodeInfoDao, ) { // hardware info about our local device (can be null) private val _myNodeInfo = MutableStateFlow(null) val myNodeInfo: StateFlow get() = _myNodeInfo // our node info private val _ourNodeInfo = MutableStateFlow(null) val ourNodeInfo: StateFlow get() = _ourNodeInfo // The unique userId of our node private val _myId = MutableStateFlow(null) val myId: StateFlow get() = _myId // A map from nodeNum to NodeInfo private val _nodeDBbyNum = MutableStateFlow>(mapOf()) val nodeDBbyNum: StateFlow> get() = _nodeDBbyNum val nodesByNum get() = nodeDBbyNum.value // A map from userId to NodeInfo private val _nodeDBbyID = MutableStateFlow>(mapOf()) val nodeDBbyID: StateFlow> get() = _nodeDBbyID val nodes get() = nodeDBbyID init { nodeInfoDao.getMyNodeInfo().onEach { _myNodeInfo.value = it } .launchIn(processLifecycle.coroutineScope) nodeInfoDao.nodeDBbyNum().onEach { _nodeDBbyNum.value = it val ourNodeInfo = it.values.firstOrNull() _ourNodeInfo.value = ourNodeInfo _myId.value = ourNodeInfo?.user?.id }.launchIn(processLifecycle.coroutineScope) nodeInfoDao.nodeDBbyID().onEach { _nodeDBbyID.value = it } .launchIn(processLifecycle.coroutineScope) } fun myNodeInfoFlow(): Flow = nodeInfoDao.getMyNodeInfo() fun nodeInfoFlow(): Flow> = nodeInfoDao.getNodes() suspend fun upsert(node: NodeInfo) = withContext(Dispatchers.IO) { nodeInfoDao.upsert(node) } suspend fun installNodeDB(mi: MyNodeInfo, nodes: List) = withContext(Dispatchers.IO) { nodeInfoDao.apply { clearNodeInfo() clearMyNodeInfo() setMyNodeInfo(mi) // set MyNodeInfo first putAll(nodes) } } }