package theorycrafter.utils

import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material.LocalContentColor
import androidx.compose.material.LocalTextStyle
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.TextFieldValue
import compose.input.KeyShortcut
import compose.input.onKeyShortcut
import compose.input.onMousePress
import compose.utils.requestInitialFocus


/**
 * UI for editing the name of an item inline (typically displayed in a list).
 */
@Composable
fun ItemNameEditor(
    itemName: String,
    modifier: Modifier = Modifier,
    onRename: (String) -> Unit,
    onEditingFinished: () -> Unit,
) {
    var textFieldValue by remember {
        mutableStateOf(
            TextFieldValue(
                text = itemName,
                selection = TextRange(0, itemName.length)
            )
        )
    }

    // Prevent onEditingFinished from being called twice before a recomposition occurs.
    // Without this when the user presses Enter (or Escape), the calling code can ask the focus to move elsewhere,
    // causing us to call onEditingFinished again.
    var calledOnEditingFinished by remember { mutableStateOf(false) }.also { it.value = false }
    fun callOnEditingFinished() {
        if (!calledOnEditingFinished) {
            // Must be set before calling, because onEditingFinished() can call onLostFocus itself
            calledOnEditingFinished = true
            onEditingFinished()
        }
    }

    val interactionSource = remember { MutableInteractionSource() }
    val color = LocalContentColor.current
    BasicTextField(
        value = textFieldValue,
        onValueChange = { textFieldValue = it },
        singleLine = true,
        textStyle = LocalTextStyle.current.copy(color = color),
        cursorBrush = SolidColor(color),
        interactionSource = interactionSource,
        modifier = modifier
            .onKeyShortcut(KeyShortcut.anyEnter(), onPreview = true) {
                onRename(textFieldValue.text)
                callOnEditingFinished()
            }
            .onKeyShortcut(Key.Escape, onPreview = true) {
                callOnEditingFinished()
            }
            .requestInitialFocus()
            // Consume the event to prevent it going to the parent list, which probably requests focus when clicked,
            // which will unfocus the textfield, cancelling the editing.
            .onMousePress(consumeEvent = true) {  }
    )

    interactionSource.onLostFocus {
        callOnEditingFinished()
    }
}
