data class FabItem(
    val imageResource : ImageVector,
    val title : String,
    val isChild : Boolean = false
)

@Composable
fun FabMenu(
    modifier: Modifier = Modifier,
    fabmenuBackground : Color = Color.White,
    childItems : List<FabItem>,
    childItemClick : (FabItem) -> Unit
){
    val rotation = remember { Animatable(0f) }
    val scope = rememberCoroutineScope()
    var fabState by remember { mutableStateOf(FabState.COLLAPSE) }
    val rootFabClicked = {
        scope.launch {
            fabState = fabState.getAlternativestate()
            rotation.animateTo(
                targetValue = if (fabState == FabState.EXPAND) {
                    rotation.targetValue + 45f
                } else rotation.targetValue - 45f,
                animationSpec = tween(100, easing = LinearEasing)
            )
        }
    }


    ConstraintLayout(
        modifier = modifier
            .fillMaxSize()
            .background(if (fabState == FabState.EXPAND) fabmenuBackground else Color.Transparent)
    ) {
        val (fabmenu) = createRefs()

        Column(
            horizontalAlignment = Alignment.End,
            modifier = Modifier
                .padding(20.dp)
                .constrainAs(fabmenu) {
                    bottom.linkTo(parent.bottom)
                    end.linkTo(parent.end)
                }
        ) {

            LazyColumn(
                horizontalAlignment = Alignment.End
            ){
                itemsIndexed(childItems){ _index, _item->
                    FabButtonChild(
                        fabState = fabState,
                        padding = 8.dp,
                        fabItem = _item
                    ){
                        childItemClick(_item)
                    }
                }
            }

            Spacer( modifier = Modifier.height(8.dp) )

            FabButton(
                padding = 16.dp,
                elevation = 8.dp,
                rotation = rotation.value,
                fabItem = FabItem(Icons.Default.Add,"", false),
                endPadding = 0.dp,
                buttonClick = {rootFabClicked()}
            )
        }
    }

}

@OptIn(ExperimentalAnimationApi::class)
@Composable
fun FabButtonChild(
    fabState : FabState,
    padding : Dp,
    elevation : Dp = 4.dp,
    fabItem: FabItem,
    childClick : () -> Unit
){
    AnimatedVisibility(
        visible = fabState == FabState.EXPAND,
        enter = scaleIn(),
        exit = scaleOut()
    ) {

        Column(
            modifier = Modifier.padding(end = 4.dp)
        ) {

            FabButton(
                rotation = 0f,
                padding = padding,
                elevation = elevation,
                buttonClick = childClick,
                fabItem = fabItem
            )

            Spacer( modifier = Modifier.height(8.dp) )

        }
    }
}

@Composable
fun FabButton(
    rotation : Float,
    elevation : Dp = 4.dp,
    endPadding : Dp = 3.dp,
    padding : Dp,
    fabItem: FabItem,
    buttonClick : () -> Unit
){

    Row (
        horizontalArrangement = Arrangement.End,
        verticalAlignment = Alignment.CenterVertically,
        modifier = Modifier.padding(end = endPadding)
    ){

        if (fabItem.title.isNotEmpty()){
            Card (
                elevation = elevation,
                backgroundColor = Purple500,
            ){
                Text(
                    text = fabItem.title,
                    modifier = Modifier.padding(
                        start = 10.dp,
                        end = 10.dp,
                        top = 4.dp,
                        bottom = 4.dp
                    )
                )
            }

            Spacer(modifier = Modifier.width(10.dp))
        }

        Card (
            elevation = elevation,
            backgroundColor = Purple500,
            shape = CircleShape,
            modifier = Modifier
                .clickable {
                    buttonClick()
                }
                .rotate(
                    if (!fabItem.isChild) {
                        rotation
                    } else 0f
                )
        ){
            Icon(
                imageVector = fabItem.imageResource,
                contentDescription = fabItem.title,
                tint = Color.White,
                modifier = Modifier
                    .padding(padding)
            )
        }
    }
}

@Composable
@Preview
fun FabMenuDisplay(){

    val list = listOf<FabItem>(
        FabItem(Icons.Default.PhotoCameraBack, "Camera", true),
        FabItem(Icons.Default.Image, "Gallery", true),
        FabItem(Icons.Default.Description, "Files", true),
    )

    FabMenu(
        modifier = Modifier,
        childItems = list,
        fabmenuBackground = Color.Black.copy(alpha = 0.1f)
    ){
    }
}