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

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.rememberCoroutineScope
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.unit.IntSize
import com.pixelized.desktop.lwa.ui.composable.scene.camera.Camera
import com.pixelized.desktop.lwa.ui.composable.scene.camera.onCameraControl
import com.pixelized.desktop.lwa.ui.composable.scene.drawables.SceneElement
import com.pixelized.desktop.lwa.ui.composable.scene.drawables.SceneLayer

@Stable
data class Scene(
    val size: IntSize,
    val layers: List<SceneLayer>,
    val elements: List<SceneElement>,
)

@Composable
fun Scene(
    modifier: Modifier = Modifier,
    camera: Camera,
    scene: Scene,
    content: @Composable BoxScope.() -> Unit,
) {
    rememberCoroutineScope()

    Box(
        modifier = Modifier
            .graphicsLayer { clip = true }
            .onCameraControl(sceneSize = scene.size, camera = camera)
            .drawLayers(camera = camera, layers = scene.layers)
            .drawElements(camera = camera, elements = scene.elements)
            .then(other = modifier),
    ) {
        content()
    }
}

@OptIn(ExperimentalComposeUiApi::class)
fun Modifier.drawLayers(
    camera: Camera,
    layers: List<SceneLayer>,
): Modifier = this.drawWithCache {
    onDrawBehind {
        layers.forEach { layers ->
            drawImage(
                image = layers.texture,
                srcOffset = camera.offset - layers.offset,
                srcSize = camera.cameraSizeZoomed,
                dstSize = camera.cameraSize,
                alpha = layers.alpha,
            )
        }
    }
}

fun Modifier.drawElements(
    camera: Camera,
    elements: List<SceneElement>,
): Modifier = this.drawWithCache {
    onDrawBehind {
        elements.forEach { element ->
            drawImage(
                image = element.texture,
                srcOffset = camera.offset - element.position,
                srcSize = camera.cameraSizeZoomed,
                dstSize = camera.cameraSize,
                alpha = element.alpha,
            )
        }
    }
}