package com.geeksville.mesh.model import androidx.lifecycle.Lifecycle import androidx.lifecycle.coroutineScope import com.geeksville.mesh.MeshProtos 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 getNodes( sort: NodeSortOption = NodeSortOption.LAST_HEARD, filter: String = "", includeUnknown: Boolean = true, ) = nodeInfoDao.getNodes( sort = sort.sqlValue, filter = filter, includeUnknown = includeUnknown, unknownHwModel = MeshProtos.HardwareModel.UNSET ) fun myNodeInfoFlow(): Flow = nodeInfoDao.getMyNodeInfo() 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) } } suspend fun deleteNode(num: Int) = withContext(Dispatchers.IO) { nodeInfoDao.deleteNode(num) } }