package dev.ulfrx.recipe.ui.screens.shell.dock

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import dev.ulfrx.recipe.navigation.DockDestination
import dev.ulfrx.recipe.ui.components.glass.CircleGlassButton
import dev.ulfrx.recipe.ui.theme.RecipeTheme
import org.jetbrains.compose.resources.stringResource
import recipe.composeapp.generated.resources.Res
import recipe.composeapp.generated.resources.dock_expand_a11y

@Composable
fun DockBar(
    destinations: List<DockDestination>,
    active: DockDestination,
    collapsed: Boolean,
    onTabSelect: (DockDestination) -> Unit,
    modifier: Modifier = Modifier,
    height: Dp = 56.dp,
) {
    if (collapsed) {
        DockBarCollapsed(
            active = active,
            onTabSelect = onTabSelect,
            modifier = modifier,
            height = height,
        )
    } else {
        DockBarExpanded(
            destinations = destinations,
            active = active,
            onTabSelect = onTabSelect,
            modifier = modifier,
            height = height,
        )
    }
}

@Composable
private fun DockBarCollapsed(
    active: DockDestination,
    onTabSelect: (DockDestination) -> Unit,
    modifier: Modifier,
    height: Dp,
) {
    CircleGlassButton(
        onClick = { onTabSelect(active) },
        icon = active.icon,
        contentDescription = stringResource(Res.string.dock_expand_a11y),
        modifier = modifier,
        size = height,
        iconTint = RecipeTheme.colors.accent,
    )
}

@Composable
private fun DockBarExpanded(
    destinations: List<DockDestination>,
    active: DockDestination,
    onTabSelect: (DockDestination) -> Unit,
    modifier: Modifier,
    height: Dp,
) {
    val tabBounds = remember { mutableStateMapOf<Int, TabBounds>() }
    var pressState by remember { mutableStateOf<DockPressState>(DockPressState.Idle) }
    var dockWidthPx by remember { mutableStateOf(0f) }
    val activeIndex = destinations.indexOf(active).coerceAtLeast(0)

    Box(
        modifier =
            modifier
                .height(height)
                .onSizeChanged { dockWidthPx = it.width.toFloat() }
                .pointerInput(destinations) {
                    trackDockGesture { event ->
                        when (event) {
                            is DockPressEvent.Pressing -> {
                                pressState = DockPressState.Pressing(event.xPx)
                            }

                            is DockPressEvent.Released -> {
                                tabIndexAt(event.xPx, tabBounds)?.let { idx ->
                                    onTabSelect(destinations[idx])
                                }
                                pressState = DockPressState.Idle
                            }

                            DockPressEvent.Cancelled -> {
                                pressState = DockPressState.Idle
                            }
                        }
                    }
                },
    ) {
        val anim =
            rememberDockOverlayAnimations(
                pressState = pressState,
                activeIndex = activeIndex,
                tabBounds = tabBounds,
                dockWidthPx = dockWidthPx,
                density = LocalDensity.current,
            )
        DockSubstrate(cornerRadius = height / 2)
        DockActiveIndicatorLayer(
            activeIndex = activeIndex,
            tabBounds = tabBounds,
            dockWidthPx = dockWidthPx,
            alpha = anim.activeIndicatorAlpha,
        )
        DockPressOverlayLayer(
            overlayCenterX = anim.overlayCenterX,
            overlayWidthPx = anim.overlayWidthPx,
            overlayAlpha = anim.overlayAlpha,
            overlayPeakProgress = anim.overlayPeakProgress,
            dockWidthPx = dockWidthPx,
            dockHeight = height,
        )
        DockTabRow(
            destinations = destinations,
            activeIndex = activeIndex,
            tabBounds = tabBounds,
            dockWidthPx = dockWidthPx,
            onTabSelectFromA11y = onTabSelect,
            onTabBoundsChange = { index, bounds -> tabBounds[index] = bounds },
        )
    }
}
