package llc.arma.ble.app.ui.screen.inspection.accelerometer

import androidx.compose.foundation.layout.Column
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.hilt.navigation.compose.hiltViewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import llc.arma.ble.app.ui.common.rememberBottomDialogState
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelFftAxisEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelFftModeEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelFrequencyEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelRealtimeViewEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelScaleEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelViewEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.DisplayState
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.HistoryEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.IntervalEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.LoadingState
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.PowerEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.Write
import llc.arma.ble.domain.model.Ble

enum class SheetPage {
    ACCEL_SCALE, SPECTRE_SCALE, HISTORY_MODE_EDIT, HISTORY_SCALE, HISTORY_EDIT, ACCEL_EDIT, ACCEL_REALTIME_EDIT, POWER, WRITE, ACCEL_MODE_EDIT, SPECTRE_MODE_EDIT, FREQUENCY_EDIT, AXIS_EDIT, FFT_MODE_EDIT, INTERVAL_EDIT
}

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun AccelerometerScreen(
    ble: Ble.Accelerometer,
    onEvent: (AccelerometerContract.Effect.Navigation) -> Unit
) {

    val viewModel = hiltViewModel<AccelerometerViewModel>()
    val state = viewModel.viewState.value

    val bottomDialog = rememberBottomDialogState()

    LaunchedEffect(ble){
        viewModel.setEvent(AccelerometerContract.Event.OnBleChanged(ble))
    }

    var sheetPage by rememberSaveable {
        mutableStateOf<SheetPage?>(null)
    }

    LaunchedEffect(
        key1 = bottomDialog.sheetState?.currentValue,
        block = {
            if(bottomDialog.sheetState?.currentValue == ModalBottomSheetValue.Hidden) {
                bottomDialog.setContent({})
                sheetPage = null
            }
        }
    )

    val scope = rememberCoroutineScope()

    LaunchedEffect(sheetPage) {
        when (sheetPage) {
            SheetPage.POWER -> bottomDialog.show {

                val currentState = viewModel.viewState.value

                if(currentState is AccelerometerContract.State.Display) {
                    PowerEdit(
                        state = currentState.accelerometer,
                        onEvent = {
                            viewModel.setEvent(it)
                        }
                    )
                }

            }
            SheetPage.WRITE -> bottomDialog.show {

                val currentState = viewModel.viewState.value

                if (currentState is AccelerometerContract.State.Display) {

                    currentState.writeState?.let {

                        Write(
                            state = it,
                            onEvent = {
                                viewModel.setEvent(it)
                            }
                        )

                    }

                }
            }
            SheetPage.ACCEL_MODE_EDIT -> bottomDialog.show {

                val currentState = viewModel.viewState.value

                if(currentState is AccelerometerContract.State.Display) {
                    AccelViewEdit(
                        next = AccelerometerContract.Event.Next.ACCEL,
                        state = currentState,
                        onEvent = {
                            viewModel.setEvent(it)
                        }
                    )
                }

            }
            SheetPage.SPECTRE_MODE_EDIT -> bottomDialog.show {

                val currentState = viewModel.viewState.value

                if(currentState is AccelerometerContract.State.Display) {
                    AccelViewEdit(
                        next = AccelerometerContract.Event.Next.ACCEL,
                        state = currentState,
                        onEvent = {
                            viewModel.setEvent(it)
                        }
                    )
                }

            }
            SheetPage.HISTORY_MODE_EDIT -> bottomDialog.show {

                val currentState = viewModel.viewState.value

                if(currentState is AccelerometerContract.State.Display) {
                    AccelViewEdit(
                        next = AccelerometerContract.Event.Next.HISTORY,
                        state = currentState,
                        onEvent = {
                            viewModel.setEvent(it)
                        }
                    )
                }

            }
            SheetPage.FREQUENCY_EDIT -> bottomDialog.show {

                val currentState = viewModel.viewState.value

                if(currentState is AccelerometerContract.State.Display) {
                    AccelFrequencyEdit(
                        state = currentState,
                        onEvent = {
                            viewModel.setEvent(it)
                        }
                    )
                }

            }
            SheetPage.AXIS_EDIT -> bottomDialog.show {

                val currentState = viewModel.viewState.value

                if(currentState is AccelerometerContract.State.Display) {
                    AccelFftAxisEdit(
                        state = currentState,
                        onEvent = {
                            viewModel.setEvent(it)
                        }
                    )
                }

            }
            SheetPage.FFT_MODE_EDIT -> bottomDialog.show {

                val currentState = viewModel.viewState.value

                if(currentState is AccelerometerContract.State.Display) {
                    AccelFftModeEdit(
                        state = currentState,
                        onEvent = {
                            viewModel.setEvent(it)
                        }
                    )
                }

            }
            SheetPage.INTERVAL_EDIT -> bottomDialog.show {

                val currentState = viewModel.viewState.value

                if(currentState is AccelerometerContract.State.Display) {
                    IntervalEdit(
                        state = currentState.accelerometer,
                        onEvent = {
                            viewModel.setEvent(it)
                        }
                    )
                }

            }
            SheetPage.ACCEL_SCALE -> bottomDialog.show {

                val currentState = viewModel.viewState.value

                if(currentState is AccelerometerContract.State.Display) {
                    AccelScaleEdit(
                        next = AccelerometerContract.Event.Next.ACCEL,
                        state = currentState,
                        onEvent = {
                            viewModel.setEvent(it)
                        }
                    )
                }

            }
            SheetPage.SPECTRE_SCALE -> bottomDialog.show {

                val currentState = viewModel.viewState.value

                if(currentState is AccelerometerContract.State.Display) {
                    AccelScaleEdit(
                        next = AccelerometerContract.Event.Next.ACCEL,
                        state = currentState,
                        onEvent = {
                            viewModel.setEvent(it)
                        }
                    )
                }

            }
            SheetPage.HISTORY_SCALE -> bottomDialog.show {

                val currentState = viewModel.viewState.value

                if(currentState is AccelerometerContract.State.Display) {
                    AccelScaleEdit(
                        next = AccelerometerContract.Event.Next.HISTORY,
                        state = currentState,
                        onEvent = {
                            viewModel.setEvent(it)
                        }
                    )
                }

            }
            SheetPage.ACCEL_EDIT -> bottomDialog.show {

                val currentState = viewModel.viewState.value

                if(currentState is AccelerometerContract.State.Display) {
                    AccelEdit(
                        state = currentState,
                        onEvent = {
                            viewModel.setEvent(it)
                        }
                    )
                }

            }
            SheetPage.HISTORY_EDIT -> bottomDialog.show {

                val currentState = viewModel.viewState.value

                if(currentState is AccelerometerContract.State.Display) {
                    HistoryEdit(
                        state = currentState,
                        onEvent = {
                            viewModel.setEvent(it)
                        }
                    )
                }

            }
            null -> {
                bottomDialog.hide()
            }

            SheetPage.ACCEL_REALTIME_EDIT -> bottomDialog.show {

                val currentState = viewModel.viewState.value

                if(currentState is AccelerometerContract.State.Display) {
                    AccelRealtimeViewEdit(
                        state = currentState,
                        onEvent = {
                            viewModel.setEvent(it)
                        }
                    )
                }

            }
        }
    }

    DisposableEffect(key1 = Unit, effect = {
        onDispose {
            scope.launch {
                bottomDialog.hide()
            }
        }
    })

    LaunchedEffect("effect"){
        viewModel.effect.onEach {
            when(it){
                is AccelerometerContract.Effect.HidePowerPicker -> launch {
                    sheetPage = null
                    delay(100)
                }
                is AccelerometerContract.Effect.ShowPowerPicker -> launch {
                    sheetPage = null
                    delay(100)
                    sheetPage = SheetPage.POWER
                }
                is AccelerometerContract.Effect.HideWriteBle -> launch {
                    sheetPage = null
                    delay(100)
                }
                is AccelerometerContract.Effect.ShowWriteBle -> launch {
                    sheetPage = null
                    delay(100)
                    sheetPage = SheetPage.WRITE
                }
                is AccelerometerContract.Effect.ShowAccelViewEdit -> launch {
                    sheetPage = null
                    delay(100)
                    sheetPage = when(it.next){
                        AccelerometerContract.Event.Next.ACCEL -> SheetPage.ACCEL_MODE_EDIT
                        AccelerometerContract.Event.Next.HISTORY -> SheetPage.HISTORY_MODE_EDIT
                    }
                }
                is AccelerometerContract.Effect.ShowFftFrequencyEdit -> launch {
                    sheetPage = null
                    delay(100)
                    sheetPage = SheetPage.FREQUENCY_EDIT
                }
                is AccelerometerContract.Effect.ShowFftAxisEdit -> launch {
                    sheetPage = null
                    delay(100)
                    sheetPage = SheetPage.AXIS_EDIT
                }
                is AccelerometerContract.Effect.ShowFftModeEdit -> launch {
                    sheetPage = null
                    delay(100)
                    sheetPage = SheetPage.FFT_MODE_EDIT
                }
                is AccelerometerContract.Effect.HideIntervalPicker -> {
                    sheetPage = null
                    delay(100)
                }
                is AccelerometerContract.Effect.ShowIntervalPicker -> {
                    sheetPage = null
                    delay(100)
                    sheetPage = SheetPage.INTERVAL_EDIT
                }
                is AccelerometerContract.Effect.ShowAccelScaleEdit -> {
                    sheetPage = null
                    delay(100)
                    sheetPage = when(it.next){
                        AccelerometerContract.Event.Next.ACCEL -> SheetPage.ACCEL_SCALE
                        AccelerometerContract.Event.Next.HISTORY -> SheetPage.HISTORY_SCALE
                    }
                }
                is AccelerometerContract.Effect.ShowAccelEdit -> {
                    sheetPage = null
                    delay(100)
                    sheetPage = SheetPage.ACCEL_EDIT
                }
                is AccelerometerContract.Effect.Navigation -> {
                    onEvent(it)
                }
                is AccelerometerContract.Effect.ShowHistoryEdit -> {
                    sheetPage = null
                    delay(100)
                    sheetPage = SheetPage.HISTORY_EDIT
                }
                is AccelerometerContract.Effect.HideHistoryEdit -> {
                    sheetPage = null
                    delay(100)
                }

                AccelerometerContract.Effect.ShowRealtimeViewModeEdit -> {
                    sheetPage = null
                    delay(100)
                    sheetPage = SheetPage.ACCEL_REALTIME_EDIT
                }

                AccelerometerContract.Effect.HideAccelEdit -> {
                    sheetPage = null
                    delay(100)
                }
            }
        }.launchIn(this)
    }

    Column {

        when(state){
            is AccelerometerContract.State.Display -> {
                DisplayState(
                    origin = state.origin,
                    ble = state.accelerometer,
                    onEvent = {
                        viewModel.setEvent(it)
                    }
                )
            }
            is AccelerometerContract.State.Loading -> LoadingState()
        }

    }

}