package com.pixelized.desktop.lwa.ui.screen.admin.character.list

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.PointerMatcher
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.onClick
import androidx.compose.material.DropdownMenu
import androidx.compose.material.DropdownMenuItem
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.minimumInteractiveComponentSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.input.pointer.PointerButton
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.screen.admin.character.list.GMCharacterItemUio.Action
import com.pixelized.desktop.lwa.ui.screen.admin.common.tag.GMTag
import com.pixelized.desktop.lwa.ui.screen.admin.common.tag.GMTagUio
import com.pixelized.desktop.lwa.ui.theme.lwa
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.game_master__character_action__add_to_group
import lwacharactersheet.composeapp.generated.resources.game_master__character_action__add_to_npc
import lwacharactersheet.composeapp.generated.resources.game_master__character_action__delete
import lwacharactersheet.composeapp.generated.resources.game_master__character_action__display_portrait
import lwacharactersheet.composeapp.generated.resources.game_master__character_action__external_link
import lwacharactersheet.composeapp.generated.resources.game_master__character_action__remove_from_group
import lwacharactersheet.composeapp.generated.resources.game_master__character_action__remove_from_npc
import lwacharactersheet.composeapp.generated.resources.game_master__character_level__label
import lwacharactersheet.composeapp.generated.resources.ic_delete_forever_24dp
import lwacharactersheet.composeapp.generated.resources.ic_face_24dp
import lwacharactersheet.composeapp.generated.resources.ic_face_retouching_off_24dp
import lwacharactersheet.composeapp.generated.resources.ic_group_24dp
import lwacharactersheet.composeapp.generated.resources.ic_group_off_24dp
import lwacharactersheet.composeapp.generated.resources.ic_imagesmode_24dp
import lwacharactersheet.composeapp.generated.resources.ic_link_24dp
import org.jetbrains.compose.resources.DrawableResource
import org.jetbrains.compose.resources.StringResource
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
import java.net.URI

@Stable
data class GMCharacterItemUio(
    val characterSheetId: String,
    val name: String,
    val job: String?,
    val level: Int,
    val tags: List<GMTagUio>,
    val actions: List<Action>,
) {
    @Stable
    sealed class Action(
        val icon: DrawableResource,
        val label: StringResource,
    ) {
        @Stable
        data object DisplayPortrait : Action(
            icon = Res.drawable.ic_imagesmode_24dp,
            label = Res.string.game_master__character_action__display_portrait,
        )

        @Stable
        data class ExternalLink(
            val externalLink: URI,
        ): Action(
            icon = Res.drawable.ic_link_24dp,
            label = Res.string.game_master__character_action__external_link,
        )

        @Stable
        data object AddToGroup : Action(
            icon = Res.drawable.ic_group_24dp,
            label = Res.string.game_master__character_action__add_to_group,
        )

        @Stable
        data object RemoveFromGroup : Action(
            icon = Res.drawable.ic_group_off_24dp,
            label = Res.string.game_master__character_action__remove_from_group,
        )

        @Stable
        data object AddToNpc : Action(
            icon = Res.drawable.ic_face_24dp,
            label = Res.string.game_master__character_action__add_to_npc,
        )

        @Stable
        data object RemoveFromNpc : Action(
            icon = Res.drawable.ic_face_retouching_off_24dp,
            label = Res.string.game_master__character_action__remove_from_npc,
        )

        @Stable
        data class DeleteCharacter(
            val characterSheetId: String,
        ) : Action(
            icon = Res.drawable.ic_delete_forever_24dp,
            label = Res.string.game_master__character_action__delete,
        )
    }
}

@Stable
object GMCharacterPreviewDefault {
    @Stable
    val padding = PaddingValues(start = 16.dp)
}

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun GMCharacter(
    modifier: Modifier = Modifier,
    padding: PaddingValues = GMCharacterPreviewDefault.padding,
    character: GMCharacterItemUio,
    onClick: () -> Unit,
    onSecondary: () -> Unit,
    onAction: (Action) -> Unit,
    onTag: (String) -> Unit,
) {
    Box(
        modifier = Modifier
            .clip(shape = MaterialTheme.lwa.shapes.gameMaster)
            .onClick(
                matcher = PointerMatcher.mouse(PointerButton.Secondary),
                onClick = onSecondary,
            )
            .clickable(onClick = onClick)
            .background(color = MaterialTheme.lwa.colorScheme.elevated.base1dp)
            .minimumInteractiveComponentSize()
            .padding(paddingValues = padding)
            .then(other = modifier),
    ) {
        Row(
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
        ) {
            Row(
                modifier = Modifier.weight(weight = 1f),
                horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
            ) {
                Text(
                    modifier = Modifier.alignByBaseline(),
                    style = MaterialTheme.lwa.typography.system.body1,
                    text = character.name,
                )
                character.job?.let {
                    Text(
                        modifier = Modifier.alignByBaseline(),
                        style = MaterialTheme.lwa.typography.system.body1,
                        fontStyle = FontStyle.Italic,
                        text = "($it)",
                    )
                }
                Text(
                    modifier = Modifier.alignByBaseline(),
                    style = MaterialTheme.lwa.typography.system.caption,
                    text = stringResource(
                        Res.string.game_master__character_level__label,
                        character.level,
                    ),
                )
            }

            character.tags.forEach { tag ->
                GMTag(
                    elevation = 4.dp,
                    tag = tag,
                    onTag = { onTag(tag.id) }
                )
            }

            OverflowActionMenu(
                character = character,
                onAction = onAction,
            )
        }
    }
}

@Composable
private fun OverflowActionMenu(
    modifier: Modifier = Modifier,
    character: GMCharacterItemUio,
    onAction: (Action) -> Unit,
) {
    val overflowMenu = remember(character) {
        mutableStateOf(false)
    }
    IconButton(
        modifier = modifier,
        onClick = {
            overflowMenu.value = true
        },
    ) {
        Icon(
            imageVector = Icons.Default.MoreVert,
            tint = MaterialTheme.colors.primary,
            contentDescription = null,
        )
        DropdownMenu(
            expanded = overflowMenu.value,
            onDismissRequest = {
                overflowMenu.value = false
            },
            content = {
                character.actions.forEach { action ->
                    DropdownMenuItem(
                        onClick = {
                            overflowMenu.value = false
                            onAction(action)
                        },
                    ) {
                        Row(
                            horizontalArrangement = Arrangement.spacedBy(space = 8.dp),
                            verticalAlignment = Alignment.CenterVertically,
                        ) {
                            Icon(
                                painter = painterResource(action.icon),
                                tint = MaterialTheme.lwa.colorScheme.base.primary,
                                contentDescription = null,
                            )
                            Text(
                                style = MaterialTheme.lwa.typography.system.body1,
                                color = MaterialTheme.lwa.colorScheme.base.primary,
                                text = stringResource(action.label),
                            )
                        }
                    }
                }
            },
        )
    }
}