package llc.arma.ble.app.ui.screen.connection

import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.animation.with
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import llc.arma.ble.app.ui.screen.inspection.accelerometer.AccelerometerScreen
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelerometerHistory
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelerometerRealtime
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelerometerSpectre
import llc.arma.ble.app.ui.screen.inspection.beacon.BeaconScreen
import llc.arma.ble.app.ui.screen.inspection.host.HostScreen
import llc.arma.ble.app.ui.screen.inspection.host.view.HostHistory
import llc.arma.ble.app.ui.screen.inspection.host.view.table.BleTableEditContract
import llc.arma.ble.app.ui.screen.inspection.host.view.table.BleTableEditScreen
import llc.arma.ble.app.ui.screen.inspection.thermometer.ThermometerScreen
import llc.arma.ble.domain.model.Ble

@OptIn(ExperimentalMaterial3Api::class, ExperimentalAnimationApi::class)
@Composable
fun ConnectionScreen(
    onNavigationEvent: (ConnectionContract.Effect.Navigation) -> Unit
) {

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

    var innerScreen by rememberSaveable {
        mutableStateOf<ConnectionContract.Effect.InnerNavigation?>(null)
    }

    BackHandler(innerScreen != null) {
        innerScreen = null
    }

    LaunchedEffect("effect"){
        viewModel.effect.onEach {
            when(it){
                is ConnectionContract.Effect.Navigation -> onNavigationEvent(it)
                is ConnectionContract.Effect.InnerNavigation -> {
                    innerScreen = it
                }
            }
        }.launchIn(this)
    }

    Box {

        Column {

            CenterAlignedTopAppBar(
                navigationIcon = {
                    IconButton(
                        onClick = {
                            if(innerScreen != null) {
                                innerScreen = null
                            } else {
                                viewModel.setEvent(ConnectionContract.Event.OnNavigateUp)
                            }
                        },
                        content = {
                            Icon(
                                imageVector = Icons.Rounded.ArrowBack,
                                contentDescription = null
                            )
                        }
                    )
                },
                title = {

                    AnimatedContent(
                        targetState = when (state) {
                            is ConnectionContract.State.Display -> state.ble.info.name
                            is ConnectionContract.State.DisplayException -> "Исключение"
                            is ConnectionContract.State.Loading -> "Соединение.."
                        },
                        transitionSpec = {
                            (slideInVertically { height -> height } + fadeIn() with
                                    slideOutVertically { height -> -height } + fadeOut()).using(
                                SizeTransform(clip = false)
                            )
                        }
                    ) { targetText ->
                        Text(
                            text = targetText
                        )
                    }

                }
            )

            when (state) {
                is ConnectionContract.State.DisplayException -> DisplayException(
                    onEvent = {
                        viewModel.setEvent(it)
                    }
                )

                is ConnectionContract.State.Loading -> LoadingState()
                is ConnectionContract.State.Display -> {
                    when (state.ble) {
                        is Ble.Beacon -> BeaconScreen(
                            ble = state.ble,
                            onNavigationEvent = {
                                viewModel.setEvent(
                                    ConnectionContract.Event.OnBeaconNavigationEvent(
                                        it
                                    )
                                )
                            }
                        )

                        is Ble.Thermometer -> {

                            Column(modifier = Modifier.weight(1f)) {

                                ThermometerScreen(
                                    ble = state.ble,
                                    onNavigationEvent = {
                                        viewModel.setEvent(
                                            ConnectionContract.Event.OnThermometerNavigationEvent(it)
                                        )
                                    }
                                )

                            }

                        }

                        is Ble.Accelerometer -> {
                            AccelerometerScreen(ble = state.ble) {
                                viewModel.setEvent(
                                    ConnectionContract.Event.OnAccelNavigationEvent(it)
                                )
                            }
                        }

                        is Ble.Host -> {
                            HostScreen(
                                ble = state.ble,
                                onNavigationEvent = {
                                    viewModel.setEvent(
                                        ConnectionContract.Event.OnHostNavigationEvent(it)
                                    )
                                }
                            )
                        }

                    }

                }

            }

        }

        innerScreen?.let {

            Surface(
                modifier = Modifier
                    .fillMaxSize()
                    .statusBarsPadding()
            ) {

                when(it){
                    is ConnectionContract.Effect.InnerNavigation.NavigateToAccelHistory -> {

                        AccelerometerHistory(
                            ble = it.ble,
                            accelMode = it.accelMode,
                            fftAxis = it.fftAxis,
                            fftMode = it.fftMode,
                            frequency = it.frequency,
                            accelScale = it.accelScale,
                            onDismiss = {
                                innerScreen = null
                            }
                        ){
                            onNavigationEvent(ConnectionContract.Effect.Navigation.NavigateToRotationsStatistic(it.ble.serial))
                        }

                    }

                    is ConnectionContract.Effect.InnerNavigation.NavigateToAccelRealtime -> {
                        AccelerometerRealtime(
                            ble = it.ble,
                            accelMode = it.accelMode,
                            fftAxis = it.fftAxis,
                            fftMode = it.fftMode,
                            frequency = it.frequency,
                            accelScale = it.accelScale,
                            onDismiss = {
                                innerScreen = null
                            }
                        )
                    }
                    is ConnectionContract.Effect.InnerNavigation.NavigateToAccelSpectre -> {
                        AccelerometerSpectre(
                            ble = it.ble,
                            accelMode = it.accelMode,
                            fftAxis = it.fftAxis,
                            fftMode = it.fftMode,
                            frequency = it.frequency,
                            accelScale = it.accelScale,
                            onDismiss = {
                                innerScreen = null
                            }
                        )
                    }

                    is ConnectionContract.Effect.InnerNavigation.NavigateToHostHistory -> {
                        HostHistory(
                            ble = it.ble,
                            onDismiss = {
                                innerScreen = null
                            }
                        )

                    }

                    is ConnectionContract.Effect.InnerNavigation.NavigateHostToBleTable -> {

                        BleTableEditScreen(it.serial){
                            when(it){
                                BleTableEditContract.Effect.Navigation.NavigateUp -> {
                                    innerScreen = null
                                }
                            }
                        }

                    }

                }

            }

        }

    }

}


@Composable
private fun LoadingState(){
    Column {
        Box(modifier = Modifier.fillMaxSize()) {
            CircularProgressIndicator(
                strokeCap = StrokeCap.Round,
                modifier = Modifier.align(Alignment.Center
                )
            )
        }
    }
}

@Composable
private fun DisplayException(
    onEvent: (ConnectionContract.Event) -> Unit
){

    Box(
        modifier = Modifier.fillMaxSize()
    ) {

        Column(
            horizontalAlignment = Alignment.CenterHorizontally,
            modifier = Modifier.align(Alignment.Center)
        ) {

            Text(
                textAlign = TextAlign.Center,
                style = MaterialTheme.typography.titleMedium,
                text = "Неудалось соединится с устройством"
            )

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

            Surface(
                modifier = Modifier
                    .height(42.dp),
                shape = CircleShape,
                color = MaterialTheme.colorScheme.primaryContainer,
                onClick = {
                    onEvent(ConnectionContract.Event.RefreshBle)
                }
            ) {

                Box(modifier = Modifier.padding(horizontal = 16.dp)) {

                    Text(
                        modifier = Modifier.align(Alignment.Center),
                        color = MaterialTheme.colorScheme.onPrimaryContainer,
                        style = MaterialTheme.typography.labelLarge,
                        text = "Повторить"
                    )

                }

            }

        }

    }

}