package com.pixelized.desktop.lwa.ui.composable.blur

import androidx.compose.animation.animateColor
import androidx.compose.animation.core.animateDp
import androidx.compose.animation.core.updateTransition
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.BlurredEdgeTreatment
import androidx.compose.ui.draw.blur
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.theme.color.LwaColorPalette
import kotlin.math.max

@Stable
class BlurContentController(
    blurred: Boolean = false,
    val blurredRadius: Dp = 8.dp,
    val scrimColor: Color = LwaColorPalette.DefaultScrimColor,
) {
    private val layer = mutableIntStateOf(if (blurred) 1 else 0)
    val isBlurred: State<Boolean> = derivedStateOf { layer.value != 0 }

    fun show() {
        layer.value += 1
    }

    fun hide() {
        layer.value = max(layer.value - 1, 0)
    }
}

@Composable
@Stable
fun rememberBlurContentController(
    blurred: Boolean = false,
    blurredRadius: Dp = 8.dp,
    scrimColor: Color = LwaColorPalette.DefaultScrimColor,
) = remember {
    BlurContentController(
        blurred = blurred,
        blurredRadius = blurredRadius,
        scrimColor = scrimColor,
    )
}

@Composable
fun BlurContent(
    modifier: Modifier = Modifier,
    controller: BlurContentController,
    content: @Composable BoxScope.() -> Unit,
) {
    val transition = updateTransition(
        targetState = controller.isBlurred.value,
    )
    val animatedBlur = transition.animateDp {
        when (it) {
            true -> controller.blurredRadius
            else -> 0.dp
        }
    }
    val animatedBackground = transition.animateColor {
        when (it) {
            true -> controller.scrimColor
            else -> controller.scrimColor.copy(alpha = 0f)
        }
    }
    Box(
        modifier = modifier
    ) {
        Box(
            modifier = Modifier
                .matchParentSize()
                .blur(
                    radius = animatedBlur.value,
                    edgeTreatment = BlurredEdgeTreatment.Unbounded,
                )
                .drawWithContent {
                    drawContent()
                    drawRect(color = animatedBackground.value)
                },
            content = content,
        )
    }
}