package com.pixelized.biblib.ui.screen.home.sort

import android.content.res.Configuration
import androidx.annotation.StringRes
import androidx.compose.animation.*
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowUpward
import androidx.compose.material.icons.filled.Menu
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.pixelized.biblib.R
import com.pixelized.biblib.model.search.SortType
import com.pixelized.biblib.model.search.SortValue
import com.pixelized.biblib.ui.composable.Handle
import com.pixelized.biblib.ui.theme.BibLibTheme
import com.pixelized.biblib.utils.extention.bibLib
import org.burnoutcrew.reorderable.*

@Stable
@Immutable
data class SortUio(
    val id: SortType,
    @StringRes val label: Int,
    val ascending: Boolean? = null,
)

@Composable
fun BookSortPage(
    viewModel: BookSortViewModel = hiltViewModel(),
    initial: Map<SortType, SortValue?>,
    onConfirm: (Map<SortType, SortValue?>) -> Unit,
) {
    LaunchedEffect(key1 = initial) {
        viewModel.update(initial)
    }
    BookSortPageContent(
        modifier = Modifier
            .fillMaxWidth()
            .navigationBarsPadding()
            .padding(vertical = 16.dp),
        state = rememberReorderableLazyListState(onMove = viewModel::onMove),
        items = viewModel.items,
        onSort = viewModel::onSort,
        onConfirm = { onConfirm(viewModel.onConfirm()) }
    )
}

@Composable
private fun BookSortPageContent(
    modifier: Modifier = Modifier,
    state: ReorderableLazyListState,
    items: State<List<SortUio>>,
    onSort: (SortUio) -> Unit,
    onConfirm: () -> Unit,
) {
    val elevation: ElevationOverlay? = LocalElevationOverlay.current

    Column(
        modifier = modifier,
        verticalArrangement = Arrangement.spacedBy(16.dp),
    ) {
        Handle(
            modifier = Modifier.align(Alignment.CenterHorizontally),
        )

        Text(
            modifier = Modifier.padding(horizontal = 16.dp),
            style = MaterialTheme.typography.h6,
            color = MaterialTheme.bibLib.colors.typography.medium,
            text = stringResource(id = R.string.search_sort_by)
        )

        LazyColumn(
            modifier = Modifier.reorderable(state),
            state = state.listState,
        ) {
            items(items = items.value, key = { it.id }) {
                ReorderableItem(state, key = it.id) { isDragging ->
                    val shadow = animateDpAsState(if (isDragging) 16.dp else 0.dp)
                    val background = elevation?.apply(
                        color = MaterialTheme.colors.surface,
                        elevation = LocalAbsoluteElevation.current + shadow.value,
                    ) ?: MaterialTheme.colors.surface

                    SortPageItem(
                        modifier = Modifier
                            .fillParentMaxWidth()
                            .height(height = 52.dp)
                            .shadow(elevation = shadow.value)
                            .background(color = background)
                            .clickable { onSort(it) }
                            .padding(horizontal = 16.dp),
                        state = state,
                        label = stringResource(id = it.label),
                        ascending = it.ascending,
                    )
                }
            }
        }

        Button(
            modifier = Modifier
                .fillMaxWidth()
                .padding(horizontal = 16.dp),
            onClick = onConfirm
        ) {
            Text(text = stringResource(id = R.string.search_sort_action))
        }
    }
}

@Composable
private fun SortPageItem(
    modifier: Modifier = Modifier,
    state: ReorderableLazyListState,
    label: String,
    ascending: Boolean?,
) {
    Row(
        modifier = modifier,
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween,
    ) {
        Row(
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(16.dp),
        ) {
            Text(
                style = MaterialTheme.typography.body1,
                color = MaterialTheme.bibLib.colors.typography.medium,
                text = label
            )

            AnimatedVisibility(
                visible = ascending != null,
                enter = fadeIn() + slideInVertically { it / 2 },
                exit = fadeOut() + slideOutVertically { it / 2 },
            ) {
                val angle by animateFloatAsState(
                    targetValue = when (ascending) {
                        true -> 0f
                        else -> 180f
                    }
                )
                Icon(
                    modifier = Modifier.rotate(degrees = angle),
                    imageVector = Icons.Default.ArrowUpward,
                    tint = MaterialTheme.bibLib.colors.typography.medium,
                    contentDescription = null,
                )
            }
        }

        Icon(
            modifier = Modifier.detectReorderAfterLongPress(state),
            imageVector = Icons.Default.Menu,
            tint = MaterialTheme.bibLib.colors.typography.medium,
            contentDescription = null,
        )
    }
}

@Composable
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun BookSortPagePreview() {
    BibLibTheme {
        val items = remember {
            mutableStateOf(
                listOf(
                    SortUio(
                        id = SortType.New,
                        label = R.string.search_sort_new,
                        ascending = true,
                    ),
                    SortUio(
                        id = SortType.Title,
                        label = R.string.search_sort_title,
                        ascending = false,
                    ),
                    SortUio(
                        id = SortType.Series,
                        label = R.string.search_sort_series,
                        ascending = null,
                    ),
                )
            )
        }
        BookSortPageContent(
            modifier = Modifier
                .fillMaxWidth()
                .padding(vertical = 16.dp),
            state = rememberReorderableLazyListState(onMove = { _, _ -> }),
            items = items,
            onSort = { },
            onConfirm = { },
        )
    }
}
