// SPDX-License-Identifier: GPL-3.0-only
package helium314.keyboard.settings.dialogs

import android.widget.Toast
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
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.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.TextFieldValue
import helium314.keyboard.latin.R
import helium314.keyboard.latin.utils.LayoutType
import helium314.keyboard.latin.utils.LayoutUtilsCustom
import helium314.keyboard.latin.utils.Log
import helium314.keyboard.latin.utils.SubtypeSettings
import helium314.keyboard.latin.utils.getStringResourceOrName
import helium314.keyboard.settings.keyboardNeedsReload
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

@Composable
fun LayoutEditDialog(
    onDismissRequest: () -> Unit,
    layoutType: LayoutType,
    initialLayoutName: String,
    startContent: String? = null,
    isNameValid: (String) -> Boolean
) {
    val ctx = LocalContext.current
    val scope = rememberCoroutineScope()
    val startIsCustom = LayoutUtilsCustom.isCustomLayout(initialLayoutName)
    var displayNameValue by rememberSaveable(stateSaver = TextFieldValue.Saver) {
        mutableStateOf(TextFieldValue(
            if (startIsCustom) LayoutUtilsCustom.getDisplayName(initialLayoutName)
            else initialLayoutName.getStringResourceOrName("layout_", ctx)
        ))
    }
    val nameValid = displayNameValue.text.isNotBlank()
            && (
                (startIsCustom && LayoutUtilsCustom.getSecondaryLayoutName(displayNameValue.text) == initialLayoutName)
                || isNameValid(LayoutUtilsCustom.getSecondaryLayoutName(displayNameValue.text))
            )

    TextInputDialog(
        onDismissRequest = {
            errorJob?.cancel()
            onDismissRequest()
        },
        onConfirmed = {
            val newLayoutName = LayoutUtilsCustom.getSecondaryLayoutName(displayNameValue.text)
            if (startIsCustom && initialLayoutName != newLayoutName) {
                LayoutUtilsCustom.getLayoutFile(initialLayoutName, layoutType, ctx).delete()
                SubtypeSettings.onRenameLayout(layoutType, initialLayoutName, newLayoutName, ctx)
            }
            LayoutUtilsCustom.getLayoutFile(newLayoutName, layoutType, ctx).writeText(it)
            LayoutUtilsCustom.onLayoutFileChanged()
            keyboardNeedsReload = true
        },
        confirmButtonText = stringResource(R.string.save),
        initialText = startContent ?: LayoutUtilsCustom.getLayoutFile(initialLayoutName, layoutType, ctx).readText(),
        singleLine = false,
        title = {
            TextField(
                value = displayNameValue,
                onValueChange = { displayNameValue = it },
                isError = !nameValid,
                supportingText = { if (!nameValid) Text(stringResource(R.string.name_invalid)) },
                trailingIcon = { if (!nameValid) Icon(painterResource(R.drawable.ic_close), null) },
            )
        },
        checkTextValid = {
            val valid = LayoutUtilsCustom.checkLayout(it, ctx)
            errorJob?.cancel()
            if (!valid) {
                errorJob = scope.launch {
                    val message = Log.getLog(10)
                        .lastOrNull { it.tag == "LayoutUtilsCustom" }?.message
                        ?.split("\n")?.take(2)?.joinToString("\n")
                    delay(3000)
                    Toast.makeText(ctx, ctx.getString(R.string.layout_error, message), Toast.LENGTH_LONG).show()
                }
            }
            valid && nameValid // don't allow saving with invalid name, but inform user about issues with layout content
        },
        // todo: this looks weird when the text field is not covered by the keyboard, but better then not seeing the bottom part of the field...
        modifier = Modifier.padding(bottom = with(LocalDensity.current)
            { (WindowInsets.ime.getBottom(LocalDensity.current) / 2 + 36).toDp() }), // why is the /2 necessary?
        reducePadding = true,
    )
}

// the job is here to make sure old jobs are canceled
private var errorJob: Job? = null
