package dev.inmo.micro_utils.repos import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.pagination.utils.doForAllWithCurrentPaging import dev.inmo.micro_utils.pagination.utils.getAllWithNextPaging import kotlinx.coroutines.flow.Flow interface ReadOneToManyKeyValueRepo : Repo { suspend fun get(k: Key, pagination: Pagination, reversed: Boolean = false): PaginationResult suspend fun keys(pagination: Pagination, reversed: Boolean = false): PaginationResult suspend fun keys(v: Value, pagination: Pagination, reversed: Boolean = false): PaginationResult suspend fun contains(k: Key): Boolean suspend fun contains(k: Key, v: Value): Boolean suspend fun count(k: Key): Long suspend fun count(): Long suspend fun getAll(k: Key, reversed: Boolean = false): List { val results = getAllWithNextPaging { get(k, it) } return if (reversed) { results.reversed() } else { results } } /** * WARNING!!! THIS METHOD PROBABLY IS NOT EFFICIENT, USE WITH CAUTION */ suspend fun getAll(reverseLists: Boolean = false): Map> = mutableMapOf>().also { map -> doWithPagination { keys(it).also { paginationResult -> paginationResult.results.forEach { k -> map[k] = getAll(k, reverseLists) } }.nextPageIfNotEmpty() } } } typealias ReadKeyValuesRepo = ReadOneToManyKeyValueRepo interface WriteOneToManyKeyValueRepo : Repo { val onNewValue: Flow> val onValueRemoved: Flow> val onDataCleared: Flow suspend fun add(toAdd: Map>) suspend fun remove(toRemove: Map>) suspend fun clear(k: Key) suspend fun clearWithValue(v: Value) suspend fun set(toSet: Map>) { toSet.keys.forEach { key -> clear(key) } add(toSet) } } typealias WriteKeyValuesRepo = WriteOneToManyKeyValueRepo suspend inline fun > REPO.add( keysAndValues: List>> ) = add(keysAndValues.toMap()) suspend inline fun > REPO.add( vararg keysAndValues: Pair> ) = add(keysAndValues.toMap()) suspend inline fun WriteOneToManyKeyValueRepo.add( k: Key, v: List ) = add(mapOf(k to v)) suspend inline fun WriteOneToManyKeyValueRepo.add( k: Key, vararg v: Value ) = add(k, v.toList()) suspend inline fun > REPO.set( keysAndValues: List>> ) = set(keysAndValues.toMap()) suspend inline fun > REPO.set( vararg keysAndValues: Pair> ) = set(keysAndValues.toMap()) suspend inline fun WriteOneToManyKeyValueRepo.set( k: Key, v: List ) = set(mapOf(k to v)) suspend inline fun WriteOneToManyKeyValueRepo.set( k: Key, vararg v: Value ) = set(k, v.toList()) interface OneToManyKeyValueRepo : ReadOneToManyKeyValueRepo, WriteOneToManyKeyValueRepo { override suspend fun clearWithValue(v: Value) { doWithPagination { val keysResult = keys(v, it) if (keysResult.results.isNotEmpty()) { remove(keysResult.results.map { it to listOf(v) }) } keysResult.currentPageIfNotEmpty() } } } typealias KeyValuesRepo = OneToManyKeyValueRepo suspend inline fun WriteOneToManyKeyValueRepo.remove( keysAndValues: List>> ) = remove(keysAndValues.toMap()) suspend inline fun WriteOneToManyKeyValueRepo.remove( vararg keysAndValues: Pair> ) = remove(keysAndValues.toMap()) suspend inline fun WriteOneToManyKeyValueRepo.remove( k: Key, v: List ) = remove(mapOf(k to v)) suspend inline fun WriteOneToManyKeyValueRepo.remove( k: Key, vararg v: Value ) = remove(k, v.toList())