package com.pixelized.desktop.lwa.ui.screen.campaign.map

import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository
import com.pixelized.desktop.lwa.repository.map.MapRepository
import com.pixelized.desktop.lwa.repository.resources.ImageResourcesRepository
import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
import com.pixelized.desktop.lwa.ui.composable.scene.Scene
import com.pixelized.desktop.lwa.ui.composable.scene.camera.Camera
import com.pixelized.desktop.lwa.ui.composable.scene.cursor.Cursor
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn

class MapSceneViewModel(
    resourcesRepository: ImageResourcesRepository,
    settingsRepository: SettingsRepository,
    campaignRepository: CampaignRepository,
    mapRepository: MapRepository,
    factory: MapSceneFactory,
) : ViewModel() {

    private val _displayDebugMenu = MutableStateFlow(false)
    val displayDebugMenu: StateFlow<Boolean> get() = _displayDebugMenu

    val enableDebug = settingsRepository.settingsFlow()
        .map { it.isGameMaster ?: false }
        .stateIn(
            scope = viewModelScope,
            started = SharingStarted.Lazily,
            initialValue = false,
        )

    private val _camera = MutableStateFlow(defaultCamera())
    val camera: StateFlow<Camera> = _camera

    private val _scene = MutableStateFlow(defaultScene())
    val scene: StateFlow<Scene> = _scene

    val enableLayersToggle: StateFlow<Boolean> = scene
        .map { it.layers.size > 1 }
        .stateIn(
            scope = viewModelScope,
            started = SharingStarted.Lazily,
            initialValue = false,
        )

    val cursor = Cursor()

    init {
        combine(
            campaignRepository.campaignFlow(),
            mapRepository.currentMap(),
        ) { campaign, map ->
            when (map) {
                null -> null
                else -> (campaign.map?.camera ?: map.camera) to map
            }
        }
            .mapNotNull { it }
            .onEach { (camera, map) ->
                _scene.value = factory.convertToScene(
                    map = map,
                    image = { resourcesRepository.load(it) },
                )
                _camera.value = factory.convertToCamera(
                    camera = camera
                )
            }
            .launchIn(scope = viewModelScope)
    }

    fun toggleDebugMenu() {
        _displayDebugMenu.value = _displayDebugMenu.value.not()
    }

    private fun defaultCamera() = Camera(
        initialZoom = 1f,
        initialOffset = IntOffset.Zero,
    )

    private fun defaultScene() = Scene(
        size = IntSize(width = 3840, height = 2160),
        layers = emptyList(),
        elements = emptyList()
    )
}