package com.ustadmobile.libuicompose.components

import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.OutlinedTextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.OffsetMapping
import androidx.compose.ui.text.input.TransformedText
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.withStyle
import com.ustadmobile.core.util.MS_PER_HOUR
import com.ustadmobile.core.util.MS_PER_MIN
import kotlin.math.min


class TimeVisualTransformation: VisualTransformation {

    private val mask = "hhmm"

    override fun filter(text: AnnotatedString): TransformedText {
        val trimmed = if(text.length >= mask.length) text.substring(mask.indices) else text.text
        val output = buildAnnotatedString {
            for(i in mask.indices) {
                if (i < trimmed.length) {
                    append(trimmed[i])
                }else {
                    withStyle(style = SpanStyle(color = Color.LightGray)) {
                        append(mask[i])
                    }
                }

                if(i == 1){
                    withStyle(style = SpanStyle(color = Color.LightGray)) {
                        append(":")
                    }
                }

            }
        }

        val offsetmapping= object: OffsetMapping {
            override fun originalToTransformed(offset: Int): Int {
                return if(offset <= 2) {
                    offset
                }else if(offset <= mask.length) {
                    offset + 1
                }else {
                    mask.length + 1 //text length plus ":"
                }
            }

            override fun transformedToOriginal(offset: Int): Int {
                val delta = if(offset <= 3) {
                    offset
                }else if(offset <= mask.length + 1) {
                    offset - 1
                }else {
                    mask.length
                }

                return min(delta, trimmed.length)
            }
        }

        return TransformedText(output, offsetmapping)

    }
}

@Composable
fun UstadTimeField(
    value: Int,
    label: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    isError: Boolean = false,
    onValueChange: (Int) -> Unit = {},
    supportingText: (@Composable () -> Unit)? = null,
) {

    fun Int.toTimeString() : String{
        return if(this > 0) {
            val hours = (this / MS_PER_HOUR)
            val mins = (this.mod(MS_PER_HOUR)) / MS_PER_MIN
            "${hours.toString().padStart(2, '0')}${mins.toString().padStart(2, '0')}"
        }else {
            ""
        }

    }

    var rawValue: String by remember(value) {
        mutableStateOf(value.toTimeString())
    }

    OutlinedTextField(
        value = rawValue,
        label = label,
        modifier = modifier,
        enabled = enabled,
        isError = isError,
        onValueChange = { newValue ->
            val filtered = newValue.filter { it.isDigit() }
            rawValue = filtered.substring(0, min(filtered.length, 4))
            if(filtered.length == 4) {
                try {
                    val hours = filtered.substring(0, 2).toInt()
                    val mins = filtered.substring(2, 4).toInt()
                    if(hours >= 0 && hours <= 23 && mins >= 0 && mins <= 59)
                        onValueChange((hours * MS_PER_HOUR) + (mins * MS_PER_MIN))
                }catch(e: Exception) {
                    //something not a valid time
                }
            }else if(filtered.isEmpty()) {
                onValueChange(0)
            }
        },
        trailingIcon = {
            UstadTimePickerAdornment(onTimeSelected = { onValueChange(it) })
        },
        visualTransformation = TimeVisualTransformation(),
        singleLine = true,
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
        supportingText = supportingText,
    )
}