package io.visus.orbis.feature.orb.ui

import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import io.visus.orbis.feature.orb.data.OrbUiState
import io.visus.orbis.feature.orb.service.OrbRenderService
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

/**
 * ViewModel for managing the Orb feature's UI state and render service interactions.
 *
 * @property renderService The service responsible for handling orb rendering operations.
 */
class OrbViewModel(
    private val renderService: OrbRenderService
) : ViewModel() {

    private val _uiState = MutableStateFlow(OrbUiState())

    /**
     * Observable UI state containing the current state of the orb feature.
     */
    val uiState: StateFlow<OrbUiState> = _uiState.asStateFlow()

    init {
        // Observe render service state
        viewModelScope.launch {
            renderService.isInitialized.collectLatest { initialized ->
                _uiState.update { it.copy(isInitialized = initialized) }
            }
        }
        viewModelScope.launch {
            renderService.error.collectLatest { error ->
                _uiState.update { it.copy(error = error) }
            }
        }
        viewModelScope.launch {
            renderService.fps.collectLatest { fps ->
                _uiState.update { it.copy(fps = fps) }
            }
        }
    }

    /**
     * Initializes the orb render service with the provided context.
     *
     * @param context The Android context required for service initialization.
     */
    fun initialize(context: Context) {
        viewModelScope.launch {
            renderService.initialize(context)
        }
    }

    /**
     * Updates the orb's amplitude.
     *
     * @param amplitude The new amplitude value.
     */
    fun updateAmplitude(amplitude: Float) {
        _uiState.update { state ->
            val newRenderState = state.renderState.copy(amplitude = amplitude)

            renderService.updateRenderState(newRenderState)

            state.copy(renderState = newRenderState)
        }
    }

    /**
     * Updates the red component of the orb's color.
     *
     * @param red The new red value (0.0 to 1.0).
     */
    fun updateRed(red: Float) {
        _uiState.update { state ->
            val currentColor = state.renderState.color
            val newColor = currentColor.copy(red = red)
            val newRenderState = state.renderState.copy(color = newColor)

            renderService.updateRenderState(newRenderState)

            state.copy(renderState = newRenderState)
        }
    }

    /**
     * Updates the green component of the orb's color.
     *
     * @param green The new green value (0.0 to 1.0).
     */
    fun updateGreen(green: Float) {
        _uiState.update { state ->
            val currentColor = state.renderState.color
            val newColor = currentColor.copy(green = green)
            val newRenderState = state.renderState.copy(color = newColor)

            renderService.updateRenderState(newRenderState)

            state.copy(renderState = newRenderState)
        }
    }

    /**
     * Updates the blue component of the orb's color.
     *
     * @param blue The new blue value (0.0 to 1.0).
     */
    fun updateBlue(blue: Float) {
        _uiState.update { state ->
            val currentColor = state.renderState.color
            val newColor = currentColor.copy(blue = blue)
            val newRenderState = state.renderState.copy(color = newColor)

            renderService.updateRenderState(newRenderState)

            state.copy(renderState = newRenderState)
        }
    }

    /**
     * Updates the alpha (transparency) component of the orb's color.
     *
     * @param alpha The new alpha value (0.0 to 1.0).
     */
    fun updateAlpha(alpha: Float) {
        _uiState.update { state ->
            val currentColor = state.renderState.color
            val newColor = currentColor.copy(alpha = alpha)
            val newRenderState = state.renderState.copy(color = newColor)

            renderService.updateRenderState(newRenderState)

            state.copy(renderState = newRenderState)
        }
    }

    /**
     * Returns the underlying render service instance.
     *
     * @return The [OrbRenderService] used by this ViewModel.
     */
    fun getRenderService(): OrbRenderService = renderService

    /**
     * Called when the ViewModel is cleared. Releases render service resources.
     */
    override fun onCleared() {
        super.onCleared()

        renderService.release()
    }
}
