package com.laseroptek.raman.ui.screens.home.energy

import android.content.res.Configuration
import android.widget.Toast
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import com.laseroptek.raman.R
import com.laseroptek.raman.const.CMD
import com.laseroptek.raman.const.READ_WRITE
import com.laseroptek.raman.const.SHOW_ENERGY_DETECT_CLOSE
import com.laseroptek.raman.data.datasource.db.RamanDatabase
import com.laseroptek.raman.data.model.serial.EnergyControl
import com.laseroptek.raman.data.model.serial.EnergyControlStop
import com.laseroptek.raman.data.model.serial.EnergyHandpiece
import com.laseroptek.raman.data.model.serial.EnergyMeasured
import com.laseroptek.raman.data.model.serial.HandPiece
import com.laseroptek.raman.data.source.db.RamanDatabaseService
import com.laseroptek.raman.repository.DatabaseRepository
import com.laseroptek.raman.repository.PreferenceRepository
import com.laseroptek.raman.repository.SerialPortRepository
import com.laseroptek.raman.ui.common.fullscreen.FullScreen
import com.laseroptek.raman.ui.screens.main.MainViewModel
import com.laseroptek.raman.ui.theme.RobotoTypography
import com.laseroptek.raman.utils.DefaultDispatcherProvider
import com.laseroptek.raman.utils.ext.dropShadow
import com.laseroptek.raman.utils.ext.innerShadow
import com.laseroptek.raman.utils.ext.px
import timber.log.Timber

/*
enum class EnergyDetectStatus {
    READY,  // INITIAL (gray - before check)
    START,  // START (yellow - ready to start or stopped)
    STOP,   // STOP (red - check started)
    ERROR,  // ERROR occured
    EXIT,   // CHECK FINISHED EXIT
}
*/

@Composable
fun EnergyDetectPopup(
    title: String = stringResource(R.string.enery_check_title),
    mainViewModel: MainViewModel = hiltViewModel<MainViewModel>(),
    onClick: () -> Unit = {}
) {
    val context = LocalContext.current

    val handPiece by mainViewModel.handPiece.collectAsState()
    val energyHandpiece by mainViewModel.energyHandpiece.collectAsState()
    val energyControl by mainViewModel.energyControl.collectAsState()

    val energyMeasured by mainViewModel.energyMeasured.collectAsState()
    val energyMeasuredWrite by mainViewModel.energyMeasuredWrite.collectAsState()
    val energyDetectRefer2 by mainViewModel.energyDetectRefer2.collectAsState()

    val voltage: Int = mainViewModel.getVoltage(10f, 10f)

    // Data class to hold all UI state variables for clarity
    data class PopupState(
        val buttonBackground: Brush,
        val buttonBorderColor: Color,
        val buttonDropShadowColor: Color,
        val buttonInnerShadowColor: Color,
        val checkHandpieceBackgroundColor: Color,
        val checkHandpieceBorderColor: Color,
        val checkDetectorBackgroundColor: Color,
        val checkDetectorBorderColor: Color,
        val errorMessage: String,
        val buttonTitle: String,
        val buttonTextColor: Color,
        val resultMessage: String,
        val resultMessageColor: Color,
        val resultBackgroundColor: Color,
        val resultBorderColor: Color,
    )

    // Default state for initialization and unknown cases
    val initialState = PopupState(
        buttonBackground = Brush.linearGradient(
            colorStops = arrayOf(
                0.0f to Color(42, 37, 20),
                1.0f to Color(72, 63, 34),
            )
        ),
        buttonBorderColor = Color(102, 87, 8),
        buttonDropShadowColor = Color(0, 0, 0).copy(alpha = 0.16f),
        buttonInnerShadowColor = Color(123, 117, 95),
        checkHandpieceBackgroundColor = Color(239, 68, 1),
        checkHandpieceBorderColor = Color(185, 28, 28),
        checkDetectorBackgroundColor = Color.Transparent,
        checkDetectorBorderColor = Color(163,163,163),
        errorMessage = "Please the tip connect to the handpiece.",
        buttonTitle = "Start",
        buttonTextColor = Color.White,
        resultMessage = "",
        resultMessageColor = Color(34,197,94),
        resultBackgroundColor = Color(248,255,255),
        resultBorderColor = Color(34,197,94)
    )

    val failState = PopupState(
        buttonBackground = Brush.linearGradient(
            colorStops = arrayOf(
                0.0f to Color(250, 250, 250),
                1.0f to Color(209, 209, 209),
            )
        ),
        buttonBorderColor = Color(199, 199, 199),
        buttonDropShadowColor = Color(0, 0, 0).copy(alpha = 0.16f),
        buttonInnerShadowColor = Color(255,255,255),
        checkHandpieceBackgroundColor = Color(74, 222, 128),
        checkHandpieceBorderColor = Color(22, 163, 74),
        checkDetectorBackgroundColor = Color(74, 222, 128),
        checkDetectorBorderColor = Color(22, 163, 74),
        errorMessage = "",
        buttonTitle = "Exit",
        resultMessage = "Fail",
        buttonTextColor = Color.Black,
        resultMessageColor = Color(220,38,38),
        resultBackgroundColor = Color(255,250,250),
        resultBorderColor = Color(248,113,113)
    )

    val goodState = PopupState(
        buttonBackground = Brush.linearGradient(
            colorStops = arrayOf(
                0.0f to Color(250, 250, 250),
                1.0f to Color(209, 209, 209),
            )
        ),
        buttonBorderColor = Color(199, 199, 199),
        buttonDropShadowColor = Color(0, 0, 0).copy(alpha = 0.16f),
        buttonInnerShadowColor = Color(255,255,255),
        checkHandpieceBackgroundColor = Color(74, 222, 128),
        checkHandpieceBorderColor = Color(22, 163, 74),
        checkDetectorBackgroundColor = Color(74, 222, 128),
        checkDetectorBorderColor = Color(22, 163, 74),
        errorMessage = "",
        buttonTitle = "Exit",
        resultMessage = "Good",
        buttonTextColor = Color.Black,
        resultMessageColor = Color(22,163,74),
        resultBackgroundColor = Color(248,255,250),
        resultBorderColor = Color(34,197,94),
    )

    Timber.d(
        "handPiece: %d, energyHandpiece: 0x%X, energyControl: 0x%X",
        handPiece.type, energyHandpiece.status, energyControl.status
    )

    val currentState = when {
        ////////////////////////////////////////////////////
        // 1 INITIAL - NO HANDPIECE
        ////////////////////////////////////////////////////
        handPiece.type == 0 -> initialState // Uses the default defined above

        ////////////////////////////////////////////////////
        // 1.2 INITIAL - H/P CONNECTED, DETECTOR CHECKING
        ////////////////////////////////////////////////////
        energyHandpiece.status != 0x47 -> initialState.copy(
            checkHandpieceBackgroundColor = Color(74, 222, 128),
            checkHandpieceBorderColor = Color(22, 163, 74),
            checkDetectorBackgroundColor = Color(239, 68, 1),
            checkDetectorBorderColor = Color(185, 28, 28),
            errorMessage = "Please the handpiece inserted into the detector."
        )

        ////////////////////////////////////////////////////
        // DETECTOR IS GOOD (status = 0x47), CHECKING energyControl
        // Ready State
        energyControl.status == 0x00 || energyControl.status == 0x42 -> initialState.copy(
            checkHandpieceBackgroundColor = Color(74, 222, 128),
            checkHandpieceBorderColor = Color(22, 163, 74),
            checkDetectorBackgroundColor = Color(74, 222, 128),
            checkDetectorBorderColor = Color(22, 163, 74),
            errorMessage = "",
            buttonTitle = "Start",
            resultMessage = "",
            buttonTextColor = Color.White,
        )

        // Start -> [Stop] State
        energyControl.status == 0x41 -> initialState.copy(
            buttonBackground = Brush.linearGradient(
                colorStops = arrayOf(
                    0.0f to Color(207, 38, 38),
                    1.0f to Color(151, 14, 14),
                )
            ),
            buttonBorderColor = Color(233, 58, 58),
            buttonDropShadowColor = Color(0, 0, 0).copy(alpha = 0.16f),
            buttonInnerShadowColor = Color(255, 173, 173),
            checkHandpieceBackgroundColor = Color(74, 222, 128),
            checkHandpieceBorderColor = Color(22, 163, 74),
            checkDetectorBackgroundColor = Color(74, 222, 128),
            checkDetectorBorderColor = Color(22, 163, 74),
            errorMessage = "",
            buttonTitle = "Stop",
            resultMessage = "",
            buttonTextColor = Color.White,
        )

        // Finish - Fail State
        energyControl.status != 0x47 -> failState

        ////////////////////////////////////////////////////////////////////////////////////////////
        // Energy Control Good

        // Finish - Good State
        energyMeasured.measured == 0 -> {
            Timber.d("Waiting for result")
            goodState.copy(
                resultMessage = "Measuring",
            )
        }

        // Condition 2: Good
        energyMeasured.measured < (energyMeasuredWrite.measured * energyDetectRefer2.good) -> {
            Timber.d("Good for result")
            goodState.copy(
                resultMessage = "Good",
            )
        }

        // Condition 3: Acceptable
        energyMeasured.measured < (energyMeasuredWrite.measured * energyDetectRefer2.acceptable) -> {
            Timber.d("Acceptable for result")
            goodState.copy(
                resultMessage = "Acceptable",
            )
        }

        // Condition 4: Bad
        energyMeasured.measured < (energyMeasuredWrite.measured * energyDetectRefer2.bad) -> {
            Timber.d("Bad for result")
            failState.copy(
                resultMessage = "Bad",
            )
        }

        // Final 'else' branch for the 'when' statement
        else -> {
            // Unknown State -> Defaults to Bad
            Timber.d("Bad (Unknown) for result")
            failState.copy(
                resultMessage = "Bad",
            )
        }
    }

    FullScreen(
        contentAlignment = Alignment.Center,
        backgroundColor = Color.Black.copy(alpha = 0.66f)
    ) {
        Column(
            modifier = Modifier
                .width(400.px.dp)
                .wrapContentHeight()
                .clip(RoundedCornerShape(28.px.dp))
                .background(Color(255, 255, 255))
                .dropShadow(
                    shape = RoundedCornerShape(28.px.dp),
                    color = Color(0, 0, 0).copy(alpha = 0.2f),
                    blur = 48.px.dp,
                    offsetX = 0.px.dp,
                    offsetY = 24.px.dp,
                    spread = 0.px.dp
                )
                .dropShadow(
                    shape = RoundedCornerShape(28.px.dp),
                    color = Color(0, 0, 0).copy(alpha = 1f),
                    blur = 6.px.dp,
                    offsetX = 0.px.dp,
                    offsetY = 3.px.dp,
                    spread = 0.px.dp
                ),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center
        ) {
            //Spacer(modifier = Modifier.size(24.px.dp))
            // Close
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(40.px.dp)
                    .padding(top = 10.px.dp, end = 20.px.dp),
                horizontalArrangement = Arrangement.End,
                verticalAlignment = Alignment.Bottom,
            ) {
                // Close (X)
                if (SHOW_ENERGY_DETECT_CLOSE) {
                    IconButton(
                        onClick = {
                            Timber.d("Now exit Energy Detect")
                            onClick.invoke()
                        },
                        modifier = Modifier.size(20.px.dp, 20.px.dp)
                    ) {
                        Image(
                            painter = painterResource(id = R.drawable.ic_close),
                            contentDescription = null,
                            modifier = Modifier.size(14.px.dp),
                            contentScale = ContentScale.Crop
                        )
                    }
                }
            }

            // title
            Row(
                modifier = Modifier
                    .size(352.px.dp, 32.px.dp),
                horizontalArrangement = Arrangement.Center,
                verticalAlignment = Alignment.CenterVertically
            ) {
                Text(
                    text = title,
                    style = RobotoTypography.bodySmall,
                    fontWeight = FontWeight.Thin,
                    fontSize = 24.px.sp,
                    color = Color.Black,
                    textAlign = TextAlign.Center
                )
            }

            // error message
            if (currentState.errorMessage != "") {
                Spacer(modifier = Modifier.size(20.px.dp))

                Row(
                    modifier = Modifier
                        .size(352.px.dp, 44.px.dp)
                        .clip(RoundedCornerShape(14.px.dp))
                        .background(Color(220, 38, 38).copy(alpha = 0.15f)),
                    horizontalArrangement = Arrangement.Center,
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    Spacer(modifier = Modifier.size(6.px.dp))

                    // Icon
                    Image(
                        painter = painterResource(id = R.drawable.ic_error),
                        contentDescription = "Background Image",
                        modifier = Modifier.size(20.px.dp),
                        contentScale = ContentScale.Crop
                    )

                    Spacer(modifier = Modifier.size(10.px.dp))

                    // errorMessage
                    Text(
                        text = currentState.errorMessage,
                        style = RobotoTypography.bodySmall,
                        fontWeight = FontWeight.ExtraLight,
                        fontSize = 12.px.sp,
                        color = Color(239,68,68),
                        textAlign = TextAlign.Center,
                    )

                    Spacer(modifier = Modifier.weight(1f))
                }
            }

            Spacer(modifier = Modifier.size(24.px.dp))

            // Check the handpiece.
            Row(
                modifier = Modifier
                    .size(352.px.dp, 41.px.dp),
                horizontalArrangement = Arrangement.Start,
                verticalAlignment = Alignment.CenterVertically
            ) {
                Spacer(modifier = Modifier.size(10.px.dp))

                Box(
                    modifier = Modifier
                        .size(16.px.dp) // Set the size to 16x16
                        .clip(CircleShape) // Clip the Box to a circle
                        .background(currentState.checkHandpieceBackgroundColor)
                        .border(
                            1.px.dp,
                            color = currentState.checkHandpieceBorderColor,
                            shape = CircleShape
                        )
                )

                Spacer(modifier = Modifier.size(15.px.dp))

                Text(
                    text = "Check the handpiece.",
                    style = RobotoTypography.bodySmall,
                    fontWeight = FontWeight.ExtraLight,
                    fontSize = 14.px.sp,
                    color = Color.Black,
                    textAlign = TextAlign.Center,
                )
            }

            // Check the energyHandpiece.
            Row(
                modifier = Modifier
                    .size(352.px.dp, 41.px.dp),
                horizontalArrangement = Arrangement.Start,
                verticalAlignment = Alignment.CenterVertically
            ) {
                Spacer(modifier = Modifier.size(10.px.dp))

                Box(
                    modifier = Modifier
                        .size(16.px.dp) // Set the size to 16x16
                        .clip(CircleShape) // Clip the Box to a circle
                        .background(currentState.checkDetectorBackgroundColor)
                        .border(
                            1.px.dp,
                            color = currentState.checkDetectorBorderColor,
                            shape = CircleShape
                        )
                )

                Spacer(modifier = Modifier.size(15.px.dp))

                Text(
                    text = "Check the energyHandpiece.",
                    style = RobotoTypography.bodySmall,
                    fontWeight = FontWeight.ExtraLight,
                    fontSize = 14.px.sp,
                    color = Color.Black,
                    textAlign = TextAlign.Center,
                )
            }

            if (currentState.resultMessage != "") {
                Spacer(modifier = Modifier.size(24.px.dp))

                Column(
                    modifier = Modifier
                        .size(352.px.dp, 92.px.dp)
                        .clip(RoundedCornerShape(12.px.dp))
                        .background(currentState.resultBackgroundColor)
                        .border(
                            1.px.dp,
                            color = currentState.resultBorderColor,
                            shape = RoundedCornerShape(12.px.dp)
                        ),
                    horizontalAlignment = Alignment.CenterHorizontally,
                    verticalArrangement = Arrangement.Center
                ) {
                    // Energy check result
                    Text(
                        text = "Energy check result",
                        style = RobotoTypography.bodySmall,
                        fontWeight = FontWeight.ExtraLight,
                        fontSize = 14.px.sp,
                        color = Color(113,113,122),
                        textAlign = TextAlign.Center,
                    )

                    Spacer(modifier = Modifier.size(4.px.dp))

                    // Result
                    Text(
                        text = currentState.resultMessage,
                        style = RobotoTypography.bodySmall,
                        fontWeight = FontWeight.ExtraLight,
                        fontSize = 22.px.sp,
                        color = currentState.resultMessageColor,
                        textAlign = TextAlign.Center,
                    )
                }
            }

            Spacer(modifier = Modifier.size(24.px.dp))

            // button
            Row(
                modifier = Modifier
                    .size(352.px.dp, 40.px.dp)
                    .clip(RoundedCornerShape(40.px.dp))
                    .background(
                        brush = currentState.buttonBackground
                    )
                    .border(
                        1.px.dp,
                        color = currentState.buttonBorderColor,
                        shape = RoundedCornerShape(40.px.dp)
                    )
                    .dropShadow(
                        shape = RoundedCornerShape(40.px.dp),
                        color = currentState.buttonDropShadowColor,
                        blur = 4.px.dp,
                        offsetX = 0.px.dp,
                        offsetY = 4.px.dp,
                        spread = 0.px.dp
                    )
                    .innerShadow(
                        shape = RoundedCornerShape(40.px.dp),
                        color = currentState.buttonInnerShadowColor,
                        blur = 1.px.dp,
                        offsetY = 1.px.dp,
                        offsetX = 0.px.dp,
                        spread = 0.px.dp
                    ),
                horizontalArrangement = Arrangement.Center,
                verticalAlignment = Alignment.CenterVertically
            ) {
                TextButton(
                    modifier = Modifier.fillMaxSize(),
                    onClick = {
                        Timber.d("Button Clicked")

                        Timber.d("handPiece: %d, energyHandpiece: 0x%X, energyControl: 0x%X, energyMeasured: %d",
                            handPiece.type, energyHandpiece.status, energyControl.status, energyMeasured.measured
                        )

                        if (handPiece.type != 0 && energyHandpiece.status == 0x47) {
                            // send start (energy control)
                            if (energyControl.status == 0x00 || energyControl.status == 0x42) { // init or stop
                                // init
                                Timber.d("Now start Energy Detect (voltage = ${voltage})")
                                Toast.makeText(
                                    context,
                                    "EnergyControl Start",
                                    Toast.LENGTH_LONG
                                ).show()

                                mainViewModel.setEnergyControl(
                                    EnergyControl(
                                        type = 0x03,
                                        status = 0x41,  // 'A': Start
                                    )
                                )

                                // initialize
                                mainViewModel.setEnergyMeasured(
                                    EnergyMeasured(
                                        type = 0x04,
                                        measured = 0,
                                        measured2 = 0,
                                    )
                                )

                                // ready: send start
                                mainViewModel.txPacket(
                                    READ_WRITE.WRITE,
                                    CMD.ENERGY_DETECT,
                                    EnergyControl(
                                        type = 0x03,
                                        status = 0x41,  // 'A': Start
                                        voltage = voltage,  // 10ms, 10J
                                    )
                                )
                            }
                            else if (energyControl.status == 0x41) {
                                Timber.d("Now Stop Energy Detect")
                                Toast.makeText(
                                    context,
                                    "EneryControl Stop",
                                    Toast.LENGTH_LONG
                                ).show()

                                // init
                                mainViewModel.setEnergyControl(
                                    EnergyControl(
                                        type = 0x03,
                                        status = 0x42,  // 'B': Stop
                                    )
                                )

                                mainViewModel.setEnergyMeasured(
                                    EnergyMeasured(
                                        type = 0x04,
                                        measured = 0
                                    )
                                )

                                // start: send stop
                                mainViewModel.txPacket(
                                    READ_WRITE.WRITE,
                                    CMD.ENERGY_DETECT,
                                    EnergyControlStop(
                                        type = 0x03,
                                        status = 0x42,  // 'B': Stop
                                    )
                                )
                            } else if (energyControl.status == 0x47 || energyControl.status == 0x4E) {
                                // 0x47 ('G') or 0x4E ('N') - Not good -> Finsih
                                Timber.d("Now exit Energy Detect")
                                onClick.invoke()
                            } else {
                                Timber.e("Unknown energy control status: ${energyControl.status}")

                                Toast.makeText(
                                    context,
                                    "Unknown energy control status: ${energyControl.status}.",
                                    Toast.LENGTH_LONG
                                ).show()
                            }
                        }
                        else {
                            Timber.e("Unable to start control - h/p: ${handPiece.type}, energyHandpiece :${energyHandpiece.status}")

                            val msg =
                                if (handPiece.type == 0)
                                    "Please the tip connect to the handpiece."
                                else
                                    "Please the handpiece inserted into the detector."

                            Toast.makeText(
                                context,
                                msg,
                                Toast.LENGTH_LONG
                            ).show()
                        }
                    },
                ) {
                    Text(
                        text = currentState.buttonTitle,
                        style = RobotoTypography.labelLarge,
                        fontWeight = FontWeight.Normal,
                        fontSize = 14.px.sp,
                        color = currentState.buttonTextColor
                    )
                }
            }

            Spacer(modifier = Modifier.size(24.px.dp))
        }
    }
}

@Preview(
    apiLevel = 34,
    uiMode = Configuration.UI_MODE_NIGHT_NO,
    showBackground = false,
    device = "spec:width=1280dp,height=720dp,dpi=150,isRound=false,chinSize=0dp,orientation=landscape"
)
@Composable
fun PreviewEnergyDetectPopup(
    mainViewModel:MainViewModel = MainViewModel(
        preferenceRepository = PreferenceRepository(LocalContext.current),
        serialPortRepository = SerialPortRepository.createWithFakeRepository(),
        databaseRepository = DatabaseRepository(RamanDatabaseService(RamanDatabase.getInstance(LocalContext.current))),
        dispatcherProvider = DefaultDispatcherProvider(),
        applicationContext = LocalContext.current
    )
) {
    // test
    mainViewModel.setHandPiece(HandPiece(type = 0))
    mainViewModel.setEnergyHandpiece(EnergyHandpiece(status = 0x47))    // 0x47('G'), 0x4E('N')
    mainViewModel.setEnergyControl(EnergyControl(status = 0x47))        // 0x47('G'), 0x4E('N')

    EnergyDetectPopup(
        title = stringResource(R.string.enery_check_title),
        mainViewModel = mainViewModel,
    )
}