package plus.rua.project.ui

import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import com.github.panpf.sketch.AsyncImage
import com.github.panpf.sketch.rememberAsyncImageState
import com.github.panpf.sketch.request.ImageOptions
import com.github.panpf.sketch.request.repeatCount
import plus.rua.project.getWebpUri
import plus.rua.project.shared.BuildConfig

/**
 * WebP 动画文件名列表，由构建期 `BuildConfig.WEBP_FILES` 注入
 * （见 `core/build.gradle.kts` 扫描 `assets/animations/` 的 `buildConfigField`）。
 *
 * `internal` 让同模块测试可直接访问（见 `AnimatedWebpFilesTest`）。
 */
internal val WEBP_FILES: List<String> = BuildConfig.WEBP_FILES.toList()

/**
 * 显示动画 WebP 图片，切换日期时随机选择一个。
 *
 * 动画无限循环播放。
 *
 * @param modifier 应用于图片的 Modifier
 * @param contentDescription 无障碍描述
 * @param seed 用于控制重新随机时机的 key，变化时重新选择 WebP
 */
@Composable
fun AnimatedWebp(
    modifier: Modifier = Modifier,
    contentDescription: String? = null,
    seed: Any? = null,
) {
    val webpFile = remember(seed) { WEBP_FILES.random() }
    val uri = remember(webpFile) { getWebpUri(webpFile) }
    val scale = remember { Animatable(0f) }

    LaunchedEffect(seed) {
        scale.snapTo(0f)
        scale.animateTo(
            targetValue = 1.1f,
            animationSpec = tween(250, easing = FastOutSlowInEasing),
        )
        scale.animateTo(
            targetValue = 1f,
            animationSpec = spring(dampingRatio = Spring.DampingRatioMediumBouncy),
        )
    }

    val state = rememberAsyncImageState(
        options = remember { ImageOptions { repeatCount(-1) } }
    )

    AsyncImage(
        uri = uri,
        contentDescription = contentDescription,
        state = state,
        modifier = modifier.graphicsLayer {
            scaleX = scale.value
            scaleY = scale.value
            alpha = scale.value.coerceIn(0f, 1f)
        },
    )
}
