/**
 * An implementation of a row of segmented buttons.
 */

package compose.widgets

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CornerBasedShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.shape.ZeroCornerSize
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.MaterialTheme
import androidx.compose.material.OutlinedButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.unit.Dp


/**
 * A widget with segmented buttons.
 */
@Composable
fun SegmentedButtons(
    selectedButton: Int?,
    onButtonSelected: (Int) -> Unit,
    modifier: Modifier = Modifier,
    shape: CornerBasedShape = MaterialTheme.shapes.small,
    border: BorderStroke = ButtonDefaults.outlinedBorder,
    contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
    minButtonHeight: Dp = ButtonDefaults.MinHeight,
    minButtonWidth: Dp = ButtonDefaults.MinWidth,
    selectedBackground: Color = MaterialTheme.colors.secondary,
    content: SegmentedButtonsScope.() -> Unit,
) {
    Row(
        modifier = modifier,
        horizontalArrangement = Arrangement.spacedBy(-border.width)
    ) {
        val buttonsContent = remember(content, this@Row) {
            val scope = object : SegmentedButtonsScope, RowScope by this {
                val buttons = mutableListOf<Pair<@Composable (Boolean) -> Unit, Boolean>>()
                override fun button(enabled: Boolean, content: @Composable (Boolean) -> Unit) {
                    buttons.add(content to enabled)
                }
            }
            scope.content()
            scope.buttons
        }

        val currentOnButtonSelected by rememberUpdatedState(onButtonSelected)

        for ((index, buttonSpec) in buttonsContent.withIndex()) {
            val isSelected = selectedButton == index
            val (buttonContent, enabled) = buttonSpec
            OutlinedButton(
                enabled = enabled,
                onClick = {
                    if (selectedButton != index)
                        currentOnButtonSelected(index)
                },
                border = border,
                shape = when {
                    buttonsContent.size == 1 -> shape
                    index == 0 -> RoundedCornerShape(
                        topStart = shape.topStart,
                        topEnd = ZeroCornerSize,
                        bottomStart = shape.bottomStart,
                        bottomEnd = ZeroCornerSize
                    )
                    index == buttonsContent.lastIndex -> RoundedCornerShape(
                        topStart = ZeroCornerSize,
                        topEnd = shape.topEnd,
                        bottomStart = ZeroCornerSize,
                        bottomEnd = shape.bottomEnd
                    )
                    else -> RectangleShape
                },
                colors = ButtonDefaults.buttonColors(
                    backgroundColor = if (isSelected) selectedBackground else MaterialTheme.colors.surface
                ),
                contentPadding = contentPadding,
                modifier = Modifier
                    .defaultMinSize(
                        minWidth = minButtonWidth,
                        minHeight = minButtonHeight
                    )
            ) {
                buttonContent(isSelected)
            }
        }
    }
}


/**
 * The scope for providing the buttons to [SegmentedButtons].
 */
interface SegmentedButtonsScope: RowScope {


    /**
     * Adds a button with the given content.
     */
    fun button(
        enabled: Boolean = true,
        content: @Composable (Boolean) -> Unit
    )


}


