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 fun getUser(userId: String?) = userId?.let { id -> nodeDBbyNum.value.values.find { it.user?.id == id }?.user } 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) } 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 clearNodeDB() = withContext(Dispatchers.IO) { nodeInfoDao.clearNodeInfo() nodeInfoDao.clearMyNodeInfo() } suspend fun installNodeDB(mi: MyNodeInfo, nodes: List) = withContext(Dispatchers.IO) { clearNodeDB() nodeInfoDao.setMyNodeInfo(mi) // set MyNodeInfo first nodeInfoDao.putAll(nodes) } suspend fun deleteNode(num: Int) = withContext(Dispatchers.IO) { nodeInfoDao.deleteNode(num) } }