package dev.inmo.postssystem.client import dev.inmo.postssystem.client.ui.fsm.* import dev.inmo.postssystem.features.auth.client.installClientAuthenticator import dev.inmo.postssystem.features.auth.common.* import dev.inmo.postssystem.features.files.client.ClientReadFilesStorage import dev.inmo.postssystem.features.files.common.storage.ReadFilesStorage import dev.inmo.postssystem.features.roles.common.Role import dev.inmo.postssystem.features.roles.common.RolesStorage import dev.inmo.postssystem.features.roles.client.ClientRolesStorage import dev.inmo.postssystem.features.roles.manager.common.RolesManagerRoleSerializer import dev.inmo.postssystem.features.users.client.UsersStorageKtorClient import dev.inmo.postssystem.features.users.common.ReadUsersStorage import dev.inmo.postssystem.features.users.common.User import dev.inmo.micro_utils.common.Either import dev.inmo.micro_utils.coroutines.LinkedSupervisorScope import dev.inmo.micro_utils.fsm.common.StatesMachine import dev.inmo.micro_utils.fsm.common.dsl.FSMBuilder import dev.inmo.micro_utils.fsm.common.managers.DefaultStatesManagerRepo import dev.inmo.micro_utils.ktor.client.UnifiedRequester import dev.inmo.micro_utils.repos.KeyValueRepo import dev.inmo.postssystem.client.settings.DefaultSettings import dev.inmo.postssystem.client.settings.Settings import dev.inmo.postssystem.client.settings.auth.AuthSettings import dev.inmo.postssystem.client.settings.auth.DefaultAuthSettings import dev.inmo.postssystem.features.common.common.* import dev.inmo.postssystem.features.content.common.ContentSerializersModuleConfigurator import dev.inmo.postssystem.features.content.common.OtherContentSerializerModuleConfigurator import dev.inmo.postssystem.features.content.text.common.TextContentSerializerModuleConfigurator import dev.inmo.postssystem.features.status.client.StatusFeatureClient import dev.inmo.postssystem.publicators.simple.client.SimplePublicatorService import dev.inmo.postssystem.publicators.simple.client.SimplePublicatorServiceClient import dev.inmo.postssystem.services.posts.client.ClientPostsService import dev.inmo.postssystem.services.posts.common.* import io.ktor.client.HttpClient import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.serialization.BinaryFormat import kotlinx.serialization.StringFormat import kotlinx.serialization.cbor.Cbor import kotlinx.serialization.json.Json import kotlinx.serialization.modules.SerializersModule import org.koin.core.Koin import org.koin.core.context.startKoin import org.koin.core.module.Module import org.koin.core.qualifier.* import org.koin.core.scope.Scope import org.koin.dsl.binds import org.koin.dsl.module val UIScopeQualifier = StringQualifier("CoroutineScopeUI") val SettingsQualifier = StringQualifier("Settings") val RolesQualifier = StringQualifier("Roles") private val FSMHandlersBuilderQualifier = StringQualifier("FSMHandlersBuilder") val defaultSerialFormat = Json { ignoreUnknownKeys = true } /** * Entrypoint for getting [org.koin.core.Koin] DI for the client * * @param repoFactory Factory for creating of [DefaultStatesManagerRepo] for [dev.inmo.postssystem.client.ui.fsm.UIFSM] */ fun baseKoin( defaultScope: CoroutineScope, settingsFactory: Scope.() -> KeyValueRepo, repoFactory: Scope.() -> DefaultStatesManagerRepo, handlersSetter: Pair>.() -> Unit ): Koin = startKoin { modules( module { singleWithRandomQualifier { OtherContentSerializerModuleConfigurator } singleWithRandomQualifier { TextContentSerializerModuleConfigurator } singleWithRandomQualifier { ContentSerializersModuleConfigurator(getAll()) } single { SerializersModuleConfigurator(getAll()) } single { Json { ignoreUnknownKeys = true serializersModule = SerializersModule { get().apply { invoke() } } } } single { get() } single(SettingsQualifier) { settingsFactory() } single { DBDropper(get(SettingsQualifier)) } single(FSMHandlersBuilderQualifier) { handlersSetter } single { repoFactory() } single { defaultScope } single(UIScopeQualifier) { get().LinkedSupervisorScope(Dispatchers.Main) } single>(UIFSMQualifier) { UIFSM(get()) { (this@single to this@UIFSM).apply(get( FSMHandlersBuilderQualifier )) } } single { DefaultAuthSettings(get(SettingsQualifier), get(), koin, get()) } single { DefaultSettings(get()) } AdditionalModules.modules.forEach { it.apply { load() } } } ) }.koin.apply { loadModules( listOf( module { single { this@apply } } ) ) RolesManagerRoleSerializer // Just to activate it in JS client } fun getAuthorizedFeaturesDIModule( serverUrl: String, initialAuthKey: Either, onAuthKeyUpdated: suspend (AuthTokenInfo) -> Unit, onUserRetrieved: suspend (User?) -> Unit, onAuthKeyInvalidated: suspend () -> Unit ): Module { val serverUrlQualifier = StringQualifier("serverUrl") val credsQualifier = StringQualifier("creds") return module { single(createdAtStart = true) { HttpClient { installClientAuthenticator(serverUrl, get(), get(credsQualifier), onAuthKeyUpdated, onUserRetrieved, onAuthKeyInvalidated) } } single(credsQualifier) { initialAuthKey } single(serverUrlQualifier) { serverUrl } single { Cbor { serializersModule = SerializersModule { get().apply { invoke() } } } } single { UnifiedRequester(get(), get()) } single { StatusFeatureClient(get(serverUrlQualifier), get()) } single { ClientReadFilesStorage(get(serverUrlQualifier), get(), get()) } single { UsersStorageKtorClient(get(serverUrlQualifier), get()) } single> { ClientRolesStorage(get(serverUrlQualifier), get(), Role.serializer()) } single { ClientPostsService(get(serverUrlQualifier), get()) } binds arrayOf( ReadPostsService::class, WritePostsService::class ) single { SimplePublicatorServiceClient(get(serverUrlQualifier), get()) } } }