package compose.widgets

import androidx.compose.foundation.*
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.v2.ScrollbarAdapter
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier


/**
 * A workaround for [issue 1916](https://github.com/JetBrains/compose-jb/issues/1916).
 */
@Composable
fun BoxScope.VerticalScrollbarInBox(
    modifier: Modifier = Modifier,
    adapter: ScrollbarAdapter,
    reverseLayout: Boolean = false,
    style: ScrollbarStyle = LocalScrollbarStyle.current,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
){
    Box(
        modifier = Modifier.matchParentSize()
    ){
        VerticalScrollbar(
            adapter = adapter,
            modifier = modifier,
            reverseLayout = reverseLayout,
            style = style,
            interactionSource = interactionSource
        )
    }
}


/**
 * A [Box] with a vertical scrollbar.
 */
@Composable
private fun VerticallyScrollableContent(
    modifier: Modifier = Modifier,
    scrollbarAdapter: ScrollbarAdapter,
    content: @Composable BoxScope.() -> Unit,
){
    Box(modifier = modifier){
        content()

        VerticalScrollbarInBox(
            modifier = Modifier.align(Alignment.TopEnd).fillMaxHeight(),
            adapter = scrollbarAdapter,
        )
    }
}


/**
 * A container with a vertical scrollbar.
 *
 * The content must apply [Modifier.verticalScroll] with [VerticallyScrollableBoxScope.scrollState] to the content
 * it wants to be scrollable.
 */
@Composable
fun ContentWithScrollbar(
    modifier: Modifier = Modifier,
    state: ScrollState = rememberScrollState(0),
    content: @Composable VerticallyScrollableBoxScope.() -> Unit,
) {
    val scrollbarAdapter = rememberScrollbarAdapter(state)
    VerticallyScrollableContent(
        modifier = modifier,
        scrollbarAdapter = scrollbarAdapter
    ) {
        val scope = remember(this, state) {
            VerticallyScrollableBoxScope(this, state)
        }
        scope.content()
    }
}


/**
 * The scope for the content in [ContentWithScrollbar].
 */
class VerticallyScrollableBoxScope(
    boxScope: BoxScope,
    val scrollState: ScrollState
): BoxScope by boxScope


/**
 * Wraps the given content in a scrollable box with a scrollbar.
 */
@Composable
fun VerticallyScrollableContent(
    modifier: Modifier = Modifier,
    state: ScrollState = rememberScrollState(0),
    content: @Composable BoxScope.() -> Unit,
) {
    ContentWithScrollbar(
        modifier = modifier,
        state = state,
    ) {
        Box(
            modifier = Modifier
                .verticalScroll(scrollState),
            content = content
        )
    }
}
