package com.pixelized.desktop.lwa

import com.pixelized.desktop.lwa.network.LwaClient
import com.pixelized.desktop.lwa.network.LwaClientImpl
import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository
import com.pixelized.desktop.lwa.repository.alteration.AlterationStore
import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository
import com.pixelized.desktop.lwa.repository.campaign.CampaignStore
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetStore
import com.pixelized.desktop.lwa.repository.inventory.InventoryRepository
import com.pixelized.desktop.lwa.repository.inventory.InventoryStore
import com.pixelized.desktop.lwa.repository.item.ItemRepository
import com.pixelized.desktop.lwa.repository.item.ItemStore
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository
import com.pixelized.desktop.lwa.repository.settings.SettingsFactory
import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
import com.pixelized.desktop.lwa.repository.settings.SettingsStore
import com.pixelized.desktop.lwa.repository.tag.TagRepository
import com.pixelized.desktop.lwa.repository.tag.TagStore
import com.pixelized.desktop.lwa.ui.composable.character.alterteration.CharacterSheetAlterationDialogFactory
import com.pixelized.desktop.lwa.ui.composable.character.alterteration.CharacterSheetAlterationDialogViewModel
import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialogFactory
import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialogViewModel
import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedDialogFactory
import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedDialogViewModel
import com.pixelized.desktop.lwa.ui.composable.character.inventory.InventoryDialogFactory
import com.pixelized.desktop.lwa.ui.composable.character.inventory.InventoryDialogViewModel
import com.pixelized.desktop.lwa.ui.composable.character.item.ItemDetailDialogFactory
import com.pixelized.desktop.lwa.ui.composable.character.item.ItemDetailDialogViewModel
import com.pixelized.desktop.lwa.ui.composable.character.purse.PurseDialogFactory
import com.pixelized.desktop.lwa.ui.composable.character.purse.PurseDialogViewModel
import com.pixelized.desktop.lwa.ui.overlay.portrait.PortraitOverlayViewModel
import com.pixelized.desktop.lwa.ui.overlay.roll.RollViewModel
import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.network.NetworkFactory
import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.network.NetworkViewModel
import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.CharacterRibbonFactory
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.sheet.CharacterDetailSheetFactory
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailPanelViewModel
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.header.CharacterDetailHeaderFactory
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.inventory.CharacterDetailInventoryFactory
import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.NpcRibbonViewModel
import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.PlayerRibbonViewModel
import com.pixelized.desktop.lwa.ui.screen.campaign.text.CampaignChatViewModel
import com.pixelized.desktop.lwa.ui.screen.campaign.text.TextMessageFactory
import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.CampaignToolbarViewModel
import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.links.ResourcesViewModel
import com.pixelized.desktop.lwa.ui.screen.gamemaster.GameMasterViewModel
import com.pixelized.desktop.lwa.ui.screen.gamemaster.action.GMActionUseCase
import com.pixelized.desktop.lwa.ui.screen.gamemaster.action.GMActionViewModel
import com.pixelized.desktop.lwa.ui.screen.gamemaster.alteration.edit.GMAlterationEditFactory
import com.pixelized.desktop.lwa.ui.screen.gamemaster.alteration.edit.GMAlterationEditViewModel
import com.pixelized.desktop.lwa.ui.screen.gamemaster.alteration.list.GMAlterationFactory
import com.pixelized.desktop.lwa.ui.screen.gamemaster.alteration.list.GMAlterationViewModel
import com.pixelized.desktop.lwa.ui.screen.gamemaster.character.edit.GMCharacterEditFactory
import com.pixelized.desktop.lwa.ui.screen.gamemaster.character.edit.GMCharacterEditViewModel
import com.pixelized.desktop.lwa.ui.screen.gamemaster.character.edit.dialog.GMCharacterSheetCopyDialogFactory
import com.pixelized.desktop.lwa.ui.screen.gamemaster.character.edit.dialog.GMCharacterSheetCopyDialogViewModel
import com.pixelized.desktop.lwa.ui.screen.gamemaster.character.list.GMCharacterFactory
import com.pixelized.desktop.lwa.ui.screen.gamemaster.character.list.GMCharacterViewModel
import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.tag.GMTagFactory
import com.pixelized.desktop.lwa.ui.screen.gamemaster.item.edit.GMItemEditFactory
import com.pixelized.desktop.lwa.ui.screen.gamemaster.item.edit.GMItemEditViewModel
import com.pixelized.desktop.lwa.ui.screen.gamemaster.item.list.GMItemFactory
import com.pixelized.desktop.lwa.ui.screen.gamemaster.item.list.GMItemViewModel
import com.pixelized.desktop.lwa.ui.screen.levelup.LevelUpFactory
import com.pixelized.desktop.lwa.ui.screen.levelup.LevelUpViewModel
import com.pixelized.desktop.lwa.ui.screen.settings.SettingsViewModel
import com.pixelized.desktop.lwa.usecase.SettingsUseCase
import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory
import com.pixelized.shared.lwa.utils.PathProvider
import io.ktor.client.HttpClient
import io.ktor.client.engine.okhttp.OkHttp
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.plugins.websocket.WebSockets
import io.ktor.serialization.kotlinx.json.json
import org.koin.core.module.dsl.factoryOf
import org.koin.core.module.dsl.singleOf
import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.module

val appModuleDependencies
    get() = listOf(
        factoryDependencies,
        useCaseDependencies,
        storeDependencies,
        repositoryDependencies,
        viewModelDependencies,
        toolsDependencies,
    )

val toolsDependencies
    get() = module {
        single {
            HttpClient(
                engine = OkHttp.create(),
            ) {
                install(WebSockets) {
                    pingIntervalMillis = 20_000
                }
                install(ContentNegotiation) {
                    json(get())
                }
            }
        }
        single<LwaClient> {
            val client: HttpClient = get()
            val setting: SettingsRepository = get()
            LwaClientImpl(client, setting)
        }
        single {
            PathProvider(appName = "LwaClient")
        }
    }

val storeDependencies
    get() = module {
        singleOf(::CharacterSheetStore)
        singleOf(::SettingsStore)
        singleOf(::AlterationStore)
        singleOf(::CampaignStore)
        singleOf(::TagStore)
        singleOf(::ItemStore)
        singleOf(::InventoryStore)
    }

val repositoryDependencies
    get() = module {
        singleOf(::NetworkRepository)
        singleOf(::CharacterSheetRepository)
        singleOf(::RollHistoryRepository)
        singleOf(::SettingsRepository)
        singleOf(::AlterationRepository)
        singleOf(::CampaignRepository)
        singleOf(::TagRepository)
        singleOf(::ItemRepository)
        singleOf(::InventoryRepository)
    }

val factoryDependencies
    get() = module {
        factoryOf(::NetworkFactory)
        factoryOf(::SettingsFactory)
        factoryOf(::CampaignJsonFactory)
        factoryOf(::CharacterRibbonFactory)
        factoryOf(::CharacterDetailHeaderFactory)
        factoryOf(::CharacterDetailSheetFactory)
        factoryOf(::CharacterDetailInventoryFactory)
        factoryOf(::CharacterSheetCharacteristicDialogFactory)
        factoryOf(::CharacterSheetDiminishedDialogFactory)
        factoryOf(::CharacterSheetAlterationDialogFactory)
        factoryOf(::InventoryDialogFactory)
        factoryOf(::ItemDetailDialogFactory)
        factoryOf(::PurseDialogFactory)
        factoryOf(::GMCharacterSheetCopyDialogFactory)
        factoryOf(::TextMessageFactory)
        factoryOf(::LevelUpFactory)
        factoryOf(::GMTagFactory)
        factoryOf(::GMCharacterFactory)
        factoryOf(::GMCharacterEditFactory)
        factoryOf(::GMAlterationFactory)
        factoryOf(::GMAlterationEditFactory)
        factoryOf(::GMItemFactory)
        factoryOf(::GMItemEditFactory)
    }

val viewModelDependencies
    get() = module {
        viewModelOf(::DataSyncViewModel)
        viewModelOf(::CampaignToolbarViewModel)
        viewModelOf(::ResourcesViewModel)
        viewModelOf(::RollViewModel)
        viewModelOf(::NetworkViewModel)
        viewModelOf(::PlayerRibbonViewModel)
        viewModelOf(::NpcRibbonViewModel)
        viewModelOf(::CharacterDetailPanelViewModel)
        viewModelOf(::CharacterSheetDiminishedDialogViewModel)
        viewModelOf(::CharacterSheetCharacteristicDialogViewModel)
        viewModelOf(::CharacterSheetAlterationDialogViewModel)
        viewModelOf(::InventoryDialogViewModel)
        viewModelOf(::ItemDetailDialogViewModel)
        viewModelOf(::PurseDialogViewModel)
        viewModelOf(::GMCharacterSheetCopyDialogViewModel)
        viewModelOf(::CampaignChatViewModel)
        viewModelOf(::SettingsViewModel)
        viewModelOf(::LevelUpViewModel)
        viewModelOf(::PortraitOverlayViewModel)
        viewModelOf(::GameMasterViewModel)
        viewModelOf(::GMCharacterViewModel)
        viewModelOf(::GMCharacterEditViewModel)
        viewModelOf(::GMActionViewModel)
        viewModelOf(::GMAlterationViewModel)
        viewModelOf(::GMAlterationEditViewModel)
        viewModelOf(::GMItemViewModel)
        viewModelOf(::GMItemEditViewModel)
    }

val useCaseDependencies
    get() = module {
        factoryOf(::SettingsUseCase)
        factoryOf(::GMActionUseCase)
    }