package mg.dot.feufaro.solfa

import androidx.compose.animation.*
import androidx.compose.animation.core.tween
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AddCircleOutline
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.material.icons.filled.RemoveCircleOutline
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.DialogProperties
import androidx.compose.ui.window.Popup
import androidx.compose.ui.window.PopupProperties

data class Marker(
    val abbr: String,
    val description: String,
    val canEditValue: Boolean = false,
    val defaultValue: String = "",
    val options: List<String> = emptyList()
)

data class MarkerGroup(
    val title: String,
    val markers: List<Marker>
)

fun getAllMarker(): List<String> {
    return markerGroups
        .flatMap { group -> group.markers }
        .map { marker -> marker.abbr }
        .filter { it != "♩=" && it != "Dô dia" }
        .sortedByDescending { it.length }
}
private val markerGroups = listOf(
    MarkerGroup(
        title = "Nuances",
        markers = listOf(
            Marker("ppp", "Très très doux"),
            Marker("pp", "Pianissimo"),
            Marker("p", "Piano"),
            Marker("mp", "Mezzo piano"),
            Marker("mf", "Mezzo forte"),
            Marker("f", "Forte"),
            Marker("ff", "Fortissimo"),
            Marker("fff", "Très très fort"),

            Marker("cres.", "Augmenter progressivement le volume"),
            Marker("<", "Crescendo"),
            Marker("decresc.", "Diminuer progressivement le volume"),
            Marker("dim.", "Diminuendo"),
            Marker(">", "Decrescendo"),

            Marker("poco", "Un peu (modifie la nuance suivante)"),
            Marker("organa", "Style ornementé"),
            Marker("sf", "Accent soudain"),
            Marker("sfz", "Sforzato"),
            Marker("fz", "Forzando"),
            Marker("rfz", "Rinforzando"),
            Marker("fp", "Forte puis immédiatement piano"),
            Marker("pf", "Piano puis forte"),
            Marker("sub.p", "Subito piano"),
            Marker("sub.f", "Subito forte")
        )
    ),

    MarkerGroup(
        title = "Tempo",
        markers = listOf(
            Marker("𝄐", "Point d'orgue"),
            Marker("Largh.", "Très très lent"),
            Marker("Grave", "Très lent et solennel"),
            Marker("Largo", "Large et lent"),
            Marker("Lento", "Lent"),
            Marker("Adagio", "Assez lent"),
            Marker("And.", "Andante"),
            Marker("Mod.", "Moderato"),
            Marker("Alleg.", "Allegretto"),
            Marker("All.", "Allegro"),
            Marker("Viv.", "Vivace"),
            Marker("Presto", "Très rapide"),
            Marker("Prestiss.", "Extrêmement rapide"),

            Marker("accel.", "Accélérer progressivement"),
            Marker("rit.", "Ralentir progressivement"),
            Marker("rall.", "Ralentir"),
            Marker("riten.", "Retenir le tempo"),
            Marker("string.", "Presser le tempo"),
            Marker("♩=", "Changement tempo", canEditValue = true, defaultValue = "60"),
            Marker("allarg.", "Élargir le tempo"),
            Marker("a_tempo", "Retour au tempo initial"),
            Marker("Tempo I", "Retour au premier tempo"),
            Marker("rubato", "Tempo libre"),
            Marker("meno_mosso", "Moins rapide"),
            Marker("più_mosso", "Plus rapide")
        )
    ),

    MarkerGroup(
        title = "Reprises",
        markers = listOf(
            Marker("D.C.", "Da Capo"),
            Marker("D.C.Fin", "Retour au début jusqu'à Fine"),
            Marker("D.C.alCoda", "Retour au début puis aller à la Coda"),
            Marker("D.S.", "Retour au Segno"),
            Marker("End", "Fin"),
            Marker("D.S.Fin", "Retour au Segno jusqu'à Fine"),
            Marker("Farany", "Fin"),
            Marker("$", "Segno"),
            Marker("Fine", "Fin"),
            Marker("Fiverenana", "Réfrain"),
            Marker("Isan\'andininy", "Réfrain"),
            Marker("Fine", "Fin"),
            Marker("𝄌", "Coda"),
            Marker("To_Coda", "Aller à la Coda"),
            Marker("||:", "Début de reprise"),
            Marker(":||", "Fin de reprise"),
            Marker("Bis", "Rejouer")
        )
    ),

    MarkerGroup(
        title = "Tonalité",
        markers = listOf(
            Marker("Dô dia", "Modulation", canEditValue = true, defaultValue = "C", options = Transpose.keyToNumber)
        )
    )
)


@Composable
@OptIn(ExperimentalComposeUiApi::class)
fun MarkerPopup(
    menuPosition: IntOffset,
    onDismiss: () -> Unit,
    onMarkerSelected: (String) -> Unit
) {
    var expandedGroupIndex by remember {
        mutableStateOf<Int?>(null)
    }
    Popup(
        offset = menuPosition,
        onDismissRequest = onDismiss,
        properties = PopupProperties(
            focusable = true,
            dismissOnBackPress = true,
            dismissOnClickOutside = true,
            usePlatformDefaultWidth = false
        )
    ) {

        Surface (
            modifier = Modifier
                .widthIn(max=250.dp)
                .heightIn(max=450.dp),
            shape = MaterialTheme.shapes.small,
            color = MaterialTheme.colorScheme.onSecondary.copy(0.75f),
        ) {
            LazyColumn {
                itemsIndexed(markerGroups) { index, group ->
                    ExpandableGroup(
                        group = group,
                        expanded = expandedGroupIndex == index,
                        onExpand = {
                            expandedGroupIndex = if(expandedGroupIndex == index) null else index
                        },
                        onMarkerSelected = {
                            onMarkerSelected(it)
                            onDismiss()
                        }
                    )
                }
            }
        }
    }
}

@OptIn(
    ExperimentalFoundationApi::class,
    ExperimentalMaterial3Api::class,
    ExperimentalLayoutApi::class
)
@Composable
private fun ExpandableGroup(
    group: MarkerGroup,
    expanded: Boolean,
    onExpand: () -> Unit,
    onMarkerSelected: (String) -> Unit
) {
    Column {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .clickable { onExpand() }
                .padding(horizontal = 12.dp, vertical = 10.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(
                text = group.title,
                modifier = Modifier.weight(1f),
                style = MaterialTheme.typography.headlineSmall.copy(
                    color = MaterialTheme.colorScheme.background
                )
            )
            Icon(
                imageVector = if (expanded)
                    Icons.Default.RemoveCircleOutline
                else
                    Icons.Default.AddCircleOutline,
                contentDescription = null,
                tint = MaterialTheme.colorScheme.primary
            )
        }

        AnimatedVisibility(
            visible = expanded,
            enter = expandVertically(
                animationSpec = tween(250)
            ) + fadeIn(
                animationSpec = tween(250)
            ),
            exit = shrinkVertically(
                animationSpec = tween(200)
            ) + fadeOut(
                animationSpec = tween(200)
            )
        ) {
            Column {
                FlowRow(
                    modifier = Modifier
                        .fillMaxWidth()
                        .heightIn(max = 220.dp)
                        .verticalScroll(rememberScrollState())
                        .padding(horizontal = 2.dp),
                    horizontalArrangement = Arrangement.spacedBy(4.dp),
                    verticalArrangement = Arrangement.spacedBy(4.dp)
                ) {
                    group.markers.forEach { marker ->
                        if (marker.canEditValue) {
                            var value by remember { mutableStateOf(marker.defaultValue) }

                            Row(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .weight(1f)
                                    .background(Color.Gray)
                                    .padding(10.dp),
                                verticalAlignment = Alignment.CenterVertically
                            ) {
                                if (marker.options.isNotEmpty()) {
                                    Text(
                                        marker.abbr,
                                        style = MaterialTheme.typography.titleMedium
                                    )
                                    var optionsExpanded by remember { mutableStateOf(false) }
                                    Box(modifier = Modifier.fillMaxWidth(0.6f)) {
                                        OutlinedButton(
                                            onClick = { optionsExpanded = true },
                                            modifier = Modifier
                                                .fillMaxWidth()
                                                .padding(2.dp)
                                        ) {
                                            Text(
                                                value,
                                                style = MaterialTheme.typography.titleLarge.copy(
                                                    fontWeight = FontWeight.Bold
                                                ),
                                                color = MaterialTheme.colorScheme.secondary
                                            )
                                        }

                                        DropdownMenu(
                                            expanded = optionsExpanded,
                                            onDismissRequest = { optionsExpanded = false }
                                        ) {
                                            marker.options.forEach { option ->
                                                DropdownMenuItem(
                                                    onClick = {
                                                        value = option
                                                        optionsExpanded = false
                                                    },
                                                    text = {
                                                        Text(option)
                                                    }
                                                )
                                            }
                                        }
                                    }
                                } else {
                                    Row(
                                        modifier = Modifier.weight(1f),
                                        verticalAlignment = Alignment.CenterVertically
                                    ) {
                                        TextField(
                                            value = value,
                                            onValueChange = { input ->
                                                value = input.filter { it.isDigit() }
                                            },
                                            modifier = Modifier.fillMaxWidth(0.70f),
                                            singleLine = true,
                                            keyboardOptions = KeyboardOptions(
                                                keyboardType = KeyboardType.Number
                                            ),
                                            leadingIcon = {
                                                Text(
                                                    text = marker.abbr,
                                                    fontSize = MaterialTheme.typography.titleMedium.fontSize,
                                                    color = MaterialTheme.colorScheme.onSecondary
                                                )
                                            },
                                            trailingIcon = {
                                                Text(
                                                    text = "bpm",
                                                    fontSize = MaterialTheme.typography.titleSmall.fontSize,
                                                    color = MaterialTheme.colorScheme.onSecondary
                                                )
                                            }
                                        )
                                        Column(
                                            horizontalAlignment = Alignment.CenterHorizontally
                                        ) {
                                            IconButton(
                                                onClick = {
                                                    val current = value.toIntOrNull() ?: 0
                                                    value = (current + 1).toString()
                                                },
                                                modifier = Modifier.size(24.dp)
                                            ) {
                                                Icon(
                                                    imageVector = Icons.Default.KeyboardArrowUp,
                                                    contentDescription = "Augmenter le tempo",
                                                    tint = Color.White
                                                )
                                            }
                                            IconButton(
                                                onClick = {
                                                    val current = value.toIntOrNull() ?: 0
                                                    value = (current - 1).coerceAtLeast(0).toString()
                                                },
                                                modifier = Modifier.size(24.dp)
                                            ) {
                                                Icon(
                                                    imageVector = Icons.Default.KeyboardArrowDown,
                                                    contentDescription = "Diminuer le tempo",
                                                    tint = Color.White
                                                )
                                            }
                                        }
                                    }
                                }
                                IconButton(
                                    onClick = {
                                        val result = marker.abbr + value
                                        onMarkerSelected(result)
                                    },
                                    modifier = Modifier.size(40.dp)
                                ) {
                                    Text(text = "✓", color = Color.White)
                                }
                            }
                        } else {
                            TooltipBox(
                                positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
                                tooltip = {
                                    PlainTooltip(
                                        containerColor = Color.DarkGray,
                                        contentColor = Color.White
                                    ) {
                                        Text(
                                            text = marker.description,
                                            fontSize = MaterialTheme.typography.bodySmall.fontSize,
                                            modifier = Modifier.padding(8.dp)
                                        )
                                    }
                                },
                                state = rememberTooltipState()
                            ) {
                                Box(
                                    modifier = Modifier
                                        .weight(1f, fill = true)
                                        .padding(4.dp)
                                        .background(Color.Gray)
                                        .clickable { onMarkerSelected(marker.abbr) }
                                        .padding(horizontal = 7.dp, vertical = 2.dp),
                                    contentAlignment = Alignment.Center
                                ) {
                                    Text(
                                        text = marker.abbr,
                                        fontSize = MaterialTheme.typography.titleSmall.fontSize,
                                        color = MaterialTheme.colorScheme.surface
                                    )
                                }
                            }
                        }
                    }
                }
                Spacer(Modifier.height(8.dp))
            }
        }
        HorizontalDivider()
    }
}