package ch.dissem.yaep.ui.common.layout

import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.layout.Placeable
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Constraints.Companion.fixed
import kotlin.math.min

internal fun Placeable.PlacementScope.squarish(
    constraints: Constraints,
    spacingPx: Int,
    grid: FocusGroup,
    horizontalClues: FocusGroup,
    verticalClues: FocusGroup,
    timeMeasurable: Measurable
) {
    val gridSize = (7 * min(constraints.maxWidth, constraints.maxHeight)) / 10
    val gridItemSize = (gridSize - 12 * spacingPx) / 18
    val rightBarWidth = constraints.maxWidth - gridSize - spacingPx

    val gridConstraints = fixed(gridSize, gridSize)
    val horizontalCluesConstraints = fixed(
        width = 3 * gridItemSize + 2 * spacingPx,
        height = gridItemSize + 2 * spacingPx
    )
    val verticalCluesConstraints = fixed(
        width = gridItemSize + 2 * spacingPx,
        height = 3 * gridItemSize + 2 * spacingPx
    )
    val timeConstraints = Constraints()


    val gridPlaceable = grid.item.measure(gridConstraints)
    val gridBoxPlaceable = grid.box.measure(gridConstraints)
    val horizontalCluesPlaceables = horizontalClues.items.map {
        it.measure(horizontalCluesConstraints)
    }
    val horizontalCluesBoxPlaceable = horizontalClues.box
        .measure(
            cluesBoxConstraints(
                width = rightBarWidth,
                itemConstraints = horizontalCluesConstraints,
                group = horizontalClues
            )
        )

    val verticalCluesPlaceables = verticalClues.items.map {
        it.measure(verticalCluesConstraints)
    }
    val verticalCluesBoxPlaceable = verticalClues.box
        .measure(
            cluesBoxConstraints(
                width = rightBarWidth,
                itemConstraints = verticalCluesConstraints,
                group = verticalClues
            )
        )
    val timePlaceable = timeMeasurable.measure(timeConstraints)

    // Position the grid
    gridBoxPlaceable.place(0, 0)
    gridPlaceable.place(0, 0)

    // Position the horizontal clues
    val horizontalCluesOffsetX = gridSize + 2 * spacingPx
    horizontalCluesBoxPlaceable.place(horizontalCluesOffsetX, 0)
    placeClues(
        placeables = horizontalCluesPlaceables,
        offsetX = horizontalCluesOffsetX,
        offsetY = 0,
        maxWidth = rightBarWidth
    )

    if (verticalClues.hasItems) {
        // Position the vertical clues
        val verticalCluesOffsetY = gridSize + 2 * spacingPx
        verticalCluesBoxPlaceable.place(0, verticalCluesOffsetY)
        placeClues(
            placeables = verticalCluesPlaceables,
            offsetX = 0,
            offsetY = verticalCluesOffsetY,
            maxWidth = gridSize
        )
    }

    // Position the time
    timePlaceable.place(
        x = constraints.maxWidth - timePlaceable.width - spacingPx,
        y = constraints.maxHeight - timePlaceable.height
    )
}
