package com.pixelized.desktop.lwa.ui.overlay.portrait

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
import com.pixelized.shared.lwa.protocol.websocket.GameMasterEvent
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.stateIn
import java.awt.Desktop
import java.net.URI

class PortraitOverlayViewModel(
    private val networkRepository: NetworkRepository,
    settingsRepository: SettingsRepository,
    characterSheetRepository: CharacterSheetRepository,
) : ViewModel() {

    @OptIn(ExperimentalCoroutinesApi::class)
    val portrait = networkRepository.data
        .mapNotNull { it as? GameMasterEvent.DisplayPortrait }
        .flatMapLatest { portrait ->
            characterSheetRepository.characterSheetPreviewFlow().map { previews ->
                previews.firstOrNull { it.characterSheetId == portrait.characterSheetId }
            }
        }
        .distinctUntilChanged()
        .map { it?.portrait }
        .stateIn(
            scope = viewModelScope,
            started = SharingStarted.Eagerly,
            initialValue = defaultPortrait()
        )

    val options = settingsRepository.settingsFlow()
        .map { settings ->
            PortraitOptionUio(
                isGameMaster = settings.isGameMaster == true,
                isBrowserAvailable = Desktop.isDesktopSupported()
                        && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)
            )
        }
        .stateIn(
            scope = viewModelScope,
            started = SharingStarted.Eagerly,
            initialValue = defaultOptions()
        )

    suspend fun dismissPortrait() {
        networkRepository.share(
            GameMasterEvent.DisplayPortrait(
                timestamp = System.currentTimeMillis(),
                characterSheetId = null,
            )
        )
    }

    fun browse(url: String) {
        if (Desktop.isDesktopSupported()) {
            val desktop = Desktop.getDesktop()
            if (desktop.isSupported(Desktop.Action.BROWSE)) {
                desktop.browse(URI.create(url))
            }
        }
    }

    private fun defaultPortrait() = null

    private fun defaultOptions() = PortraitOptionUio(
        isGameMaster = false,
        isBrowserAvailable = false,
    )
}