package com.pixelized.biblib.ui.composable.scaffold

import androidx.activity.compose.BackHandler
import androidx.compose.material.*
import androidx.compose.material.ModalBottomSheetValue.Hidden
import androidx.compose.runtime.*
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import com.pixelized.biblib.model.search.SortType
import com.pixelized.biblib.model.search.SortValue
import com.pixelized.biblib.ui.screen.home.sort.BookSortPage
import com.pixelized.biblib.utils.extention.bibLib
import kotlinx.coroutines.CancellableContinuation
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlin.coroutines.resume

val LocalSortBottomSheetState = staticCompositionLocalOf<SortBottomSheetState> {
    error("LocalSortBottomSheetState not yet ready")
}

@Stable
class SortBottomSheetState {
    private val mutex = Mutex()

    var sortBy by mutableStateOf<Map<SortType, SortValue?>>(emptyMap())
        private set

    var currentBottomSheetData by mutableStateOf<SortBottomSheetData?>(value = null)
        private set

    suspend fun show(sortBy: Map<SortType, SortValue?>): SortBottomSheetResult = mutex.withLock {
        try {
            return suspendCancellableCoroutine { continuation ->
                this.sortBy = sortBy
                currentBottomSheetData = SortBottomSheetDataImpl(continuation)
            }
        } finally {
            currentBottomSheetData = null
        }
    }

    @Stable
    private class SortBottomSheetDataImpl(
        private val continuation: CancellableContinuation<SortBottomSheetResult>
    ) : SortBottomSheetData {
        override fun performAction(sorting: Map<SortType, SortValue?>) {
            if (continuation.isActive) continuation.resume(
                SortBottomSheetResult.ActionPerformed(sortBy = sorting),
            )
        }

        override fun dismiss() {
            if (continuation.isActive) continuation.resume(
                SortBottomSheetResult.Dismissed,
            )
        }
    }
}

interface SortBottomSheetData {
    fun performAction(sorting: Map<SortType, SortValue?>)
    fun dismiss()
}

sealed class SortBottomSheetResult {
    data class ActionPerformed(val sortBy: Map<SortType, SortValue?>) : SortBottomSheetResult()
    object Dismissed : SortBottomSheetResult()
}

@Composable
fun rememberSortBottomSheetState(): SortBottomSheetState = remember {
    SortBottomSheetState()
}

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun SortBottomSheet(
    bottomSheetState: ModalBottomSheetState = rememberModalBottomSheetState(
        initialValue = Hidden,
        skipHalfExpanded = true,
    ),
    sheetShape: Shape = MaterialTheme.bibLib.shapes.sheet,
    sheetState: SortBottomSheetState = rememberSortBottomSheetState(),
    content: @Composable () -> Unit,
) {
    CompositionLocalProvider(
        LocalSortBottomSheetState provides sheetState,
    ) {
        val currentBottomSheetData = sheetState.currentBottomSheetData

        // Check the state of the currentALOBottomSheetData and show / hide the bottomSheet accordingly.
        HandleBottomSheetData(
            bottomSheetData = currentBottomSheetData,
            shouldShow = { bottomSheetState.show() },
            shouldDismiss = { bottomSheetState.hide() },
        )
        // Check the state of the bottomSheetState and call for dismiss if needed.
        HandleBottomSheetDismiss(
            bottomSheetState = bottomSheetState,
            onDismiss = { currentBottomSheetData?.dismiss() }
        )
        // Handle back event.
        BackHandler(
            enabled = bottomSheetState.isVisible,
            onBack = { currentBottomSheetData?.dismiss() },
        )

        ModalBottomSheetLayout(
            sheetState = bottomSheetState,
            content = content,
            sheetShape = sheetShape,
            scrimColor = Color.Transparent,
            sheetContent = {
                BookSortPage(
                    initial = sheetState.sortBy,
                    onConfirm = {
                        currentBottomSheetData?.performAction(it)
                    }
                )
            },
        )
    }
}