package com.example.ui.screens 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.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ClearAll import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.KeyboardArrowDown import androidx.compose.material.icons.filled.KeyboardArrowUp import androidx.compose.material.icons.filled.MusicNote import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.filled.QueueMusic import androidx.compose.material.icons.filled.Repeat import androidx.compose.material.icons.filled.RepeatOne import androidx.compose.material.icons.filled.Shuffle import androidx.compose.material.icons.filled.Videocam import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.media3.common.util.UnstableApi import com.example.data.model.MediaItemData import com.example.data.model.RepeatMode import com.example.playback.PlaybackManager import com.example.ui.theme.AccentViolet import com.example.ui.theme.AccentVioletDim import com.example.ui.theme.AmoledBlack import com.example.ui.theme.DividerSubtle import com.example.ui.theme.SurfaceElevated import com.example.ui.theme.SurfaceSecondary import com.example.ui.theme.TextPrimary import com.example.ui.theme.TextSecondary import com.example.ui.viewmodel.MainViewModel @OptIn(UnstableApi::class) @Composable fun QueueScreen( viewModel: MainViewModel, onPlayQueueItem: (MediaItemData) -> Unit, modifier: Modifier = Modifier ) { val queue by PlaybackManager.queue.collectAsState() val queueIndex by PlaybackManager.queueIndex.collectAsState() val currentItem by PlaybackManager.currentMediaItem.collectAsState() val isShuffle by PlaybackManager.isShuffleEnabled.collectAsState() val repeatMode by PlaybackManager.repeatMode.collectAsState() Column( modifier = modifier .fillMaxSize() .background(AmoledBlack) .statusBarsPadding() .testTag("queue_screen") ) { // Header Row( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 12.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { Column { Text( text = "Playback Queue", color = TextPrimary, style = MaterialTheme.typography.headlineMedium, fontWeight = FontWeight.Bold ) Text( text = "${queue.size} items in queue", color = TextSecondary, fontSize = 12.sp ) } Row(verticalAlignment = Alignment.CenterVertically) { IconButton( onClick = { PlaybackManager.toggleShuffle() }, modifier = Modifier.testTag("queue_shuffle_btn") ) { Icon( imageVector = Icons.Default.Shuffle, contentDescription = "Shuffle", tint = if (isShuffle) AccentViolet else TextSecondary ) } IconButton( onClick = { val next = when (repeatMode) { RepeatMode.OFF -> RepeatMode.ALL RepeatMode.ALL -> RepeatMode.ONE RepeatMode.ONE -> RepeatMode.OFF } PlaybackManager.setRepeatMode(next) }, modifier = Modifier.testTag("queue_repeat_btn") ) { Icon( imageVector = if (repeatMode == RepeatMode.ONE) Icons.Default.RepeatOne else Icons.Default.Repeat, contentDescription = "Repeat Mode", tint = if (repeatMode != RepeatMode.OFF) AccentViolet else TextSecondary ) } if (queue.isNotEmpty()) { IconButton( onClick = { PlaybackManager.clearQueue() }, modifier = Modifier.testTag("queue_clear_btn") ) { Icon(imageVector = Icons.Default.ClearAll, contentDescription = "Clear Queue", tint = TextSecondary) } } } } if (queue.isEmpty()) { Box( modifier = Modifier .fillMaxSize() .padding(32.dp), contentAlignment = Alignment.Center ) { Column(horizontalAlignment = Alignment.CenterHorizontally) { Icon(imageVector = Icons.Default.QueueMusic, contentDescription = null, tint = AccentViolet, modifier = Modifier.size(56.dp)) Spacer(modifier = Modifier.height(12.dp)) Text("Queue is empty.", color = TextSecondary) Spacer(modifier = Modifier.height(8.dp)) Text("Add items from your music or video library.", color = TextSecondary, fontSize = 12.sp) } } } else { LazyColumn( modifier = Modifier .fillMaxSize() .padding(horizontal = 16.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { itemsIndexed(queue, key = { index, item -> "${item.id}_$index" }) { index, item -> val isCurrent = index == queueIndex Surface( modifier = Modifier .fillMaxWidth() .clip(RoundedCornerShape(12.dp)) .clickable { PlaybackManager.setQueue(queue, index, autoPlay = true) } .testTag("queue_item_$index"), color = if (isCurrent) AccentVioletDim else SurfaceSecondary ) { Row( modifier = Modifier.padding(12.dp), verticalAlignment = Alignment.CenterVertically ) { // Playing indicator or index Box( modifier = Modifier .size(36.dp) .clip(RoundedCornerShape(8.dp)) .background(if (isCurrent) AccentViolet else SurfaceElevated), contentAlignment = Alignment.Center ) { if (isCurrent) { Icon(imageVector = Icons.Default.PlayArrow, contentDescription = "Playing", tint = AmoledBlack, modifier = Modifier.size(20.dp)) } else { Text(text = "${index + 1}", color = TextSecondary, fontSize = 12.sp, fontWeight = FontWeight.Bold) } } Spacer(modifier = Modifier.width(12.dp)) Column(modifier = Modifier.weight(1f)) { Text( text = item.title, color = if (isCurrent) AccentViolet else TextPrimary, fontSize = 14.sp, fontWeight = if (isCurrent) FontWeight.Bold else FontWeight.Medium, maxLines = 1, overflow = TextOverflow.Ellipsis ) Text( text = "${item.artist} • ${item.formattedDuration}", color = TextSecondary, fontSize = 12.sp, maxLines = 1, overflow = TextOverflow.Ellipsis ) } // Reorder Buttons (Move Up / Down) if (index > 0) { IconButton( onClick = { PlaybackManager.reorderQueue(index, index - 1) }, modifier = Modifier.size(32.dp) ) { Icon(imageVector = Icons.Default.KeyboardArrowUp, contentDescription = "Move Up", tint = TextSecondary, modifier = Modifier.size(18.dp)) } } if (index < queue.lastIndex) { IconButton( onClick = { PlaybackManager.reorderQueue(index, index + 1) }, modifier = Modifier.size(32.dp) ) { Icon(imageVector = Icons.Default.KeyboardArrowDown, contentDescription = "Move Down", tint = TextSecondary, modifier = Modifier.size(18.dp)) } } // Remove from Queue IconButton( onClick = { PlaybackManager.removeFromQueue(index) }, modifier = Modifier.size(32.dp) ) { Icon(imageVector = Icons.Default.Delete, contentDescription = "Remove", tint = TextSecondary, modifier = Modifier.size(18.dp)) } } } } } } } }