package de.sebse.fuplanner2.ui.shared

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.lazy.GridCells
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun VerticalGrid(
    cells: GridCells,
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {
    val columns: Int = when (cells) {
        is GridCells.Fixed -> {
            cells.count
        }
        is GridCells.Adaptive -> {
            val width = LocalContext.current.resources.displayMetrics.widthPixels
            val columnWidthPx = with(LocalDensity.current) { cells.minSize.toPx() }
            ((width / columnWidthPx).toInt()).coerceAtLeast(1)
        }
    }

    Layout(
        content = content,
        modifier = modifier
    ) { measurables, constraints ->
        val itemWidth = constraints.maxWidth / columns
        // Keep given height constraints, but set an exact width
        val itemConstraints = constraints.copy(
            minWidth = itemWidth,
            maxWidth = itemWidth
        )
        // Measure each item with these constraints
        val placeables = measurables.map { measurable ->
            measurable.measure(itemConstraints)
        }
        // Track each columns height so we can calculate the overall height
        val columnHeights = Array(columns) { 0 }
        placeables.forEachIndexed { index, placeable ->
            val column = index % columns
            columnHeights[column] += placeable.height
        }
        val height = (columnHeights.maxOrNull() ?: constraints.minHeight)
            .coerceAtMost(constraints.maxHeight)
        layout(constraints.maxWidth, height) {
            // Track the Y co-ord per column we have placed up to
            val columnY = Array(columns) { 0 }
            placeables.forEachIndexed { index, placeable ->
                val column = index % columns
                placeable.place(
                    x = column * itemWidth,
                    y = columnY[column]
                )
                columnY[column] += placeable.height
            }
        }
    }
}
