package dev.inmo.micro_utils.repos import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.pagination.utils.paginate import dev.inmo.micro_utils.pagination.utils.reverse import kotlinx.coroutines.flow.* class MapReadOneToManyKeyValueRepo( private val map: Map> = emptyMap() ) : ReadOneToManyKeyValueRepo { override suspend fun get(k: Key, pagination: Pagination, reversed: Boolean): PaginationResult { val list = map[k] ?: return emptyPaginationResult() return list.paginate( if (reversed) { pagination.reverse(list.size) } else { pagination } ) } override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult { val keys = map.keys val actualPagination = if (reversed) pagination.reverse(keys.size) else pagination return keys.paginate(actualPagination).let { if (reversed) { it.copy(results = it.results.reversed()) } else { it } } } override suspend fun keys(v: Value, pagination: Pagination, reversed: Boolean): PaginationResult { val keys = map.keys.filter { map[it] ?.contains(v) == true } val actualPagination = if (reversed) pagination.reverse(keys.size) else pagination return keys.paginate(actualPagination).let { if (reversed) { it.copy(results = it.results.reversed()) } else { it } } } override suspend fun contains(k: Key): Boolean = map.containsKey(k) override suspend fun contains(k: Key, v: Value): Boolean = map[k] ?.contains(v) == true override suspend fun count(k: Key): Long = map[k] ?.size ?.toLong() ?: 0L override suspend fun count(): Long = map.size.toLong() } class MapWriteOneToManyKeyValueRepo( private val map: MutableMap> = mutableMapOf() ) : WriteOneToManyKeyValueRepo { private val _onNewValue: MutableSharedFlow> = MutableSharedFlow() override val onNewValue: Flow> = _onNewValue.asSharedFlow() private val _onValueRemoved: MutableSharedFlow> = MutableSharedFlow() override val onValueRemoved: Flow> = _onValueRemoved.asSharedFlow() private val _onDataCleared: MutableSharedFlow = MutableSharedFlow() override val onDataCleared: Flow = _onDataCleared.asSharedFlow() override suspend fun add(toAdd: Map>) { toAdd.keys.forEach { k -> if (map.getOrPut(k) { mutableListOf() }.addAll(toAdd[k] ?: return@forEach)) { toAdd[k] ?.forEach { v -> _onNewValue.emit(k to v) } } } } override suspend fun remove(toRemove: Map>) { toRemove.keys.forEach { k -> if (map[k] ?.removeAll(toRemove[k] ?: return@forEach) == true) { toRemove[k] ?.forEach { v -> _onValueRemoved.emit(k to v) } } } } override suspend fun clear(k: Key) { map.remove(k) ?.also { _onDataCleared.emit(k) } } override suspend fun clearWithValue(v: Value) { map.forEach { (k, values) -> if (values.remove(v)) _onValueRemoved.emit(k to v) } } } class MapOneToManyKeyValueRepo( private val map: MutableMap> = mutableMapOf() ) : OneToManyKeyValueRepo, ReadOneToManyKeyValueRepo by MapReadOneToManyKeyValueRepo(map), WriteOneToManyKeyValueRepo by MapWriteOneToManyKeyValueRepo(map) fun MutableMap>.asOneToManyKeyValueRepo(): OneToManyKeyValueRepo = MapOneToManyKeyValueRepo( map { (k, v) -> k to v.toMutableList() }.toMap().toMutableMap() )