import { createSlice, type PayloadAction } from '@reduxjs/toolkit'; export type QueueSource = | 'manual' | 'album' | 'playlist' | 'artist' | 'search' | 'radio'; export interface QueueEntry { trackId: string; title: string; artistName: string; albumTitle: string; durationMs: number; albumArtUrl?: string; } export interface QueueState { entries: QueueEntry[]; currentIndex: number; source: QueueSource; sourceId: string | null; sourceName: string | null; shuffle: boolean; loop: boolean; } export const queueInitialState: QueueState = { entries: [], currentIndex: -1, source: 'manual', sourceId: null, sourceName: null, shuffle: false, loop: false, }; export const queueSlice = createSlice({ name: 'queue', initialState: queueInitialState, reducers: { setQueue( state, action: PayloadAction<{ entries: QueueEntry[]; startIndex?: number; source: QueueSource; sourceId?: string; sourceName?: string; }>, ) { state.entries = action.payload.entries; state.currentIndex = action.payload.startIndex ?? 0; state.source = action.payload.source; state.sourceId = action.payload.sourceId ?? null; state.sourceName = action.payload.sourceName ?? null; }, addToQueue(state, action: PayloadAction) { state.entries.push(action.payload); }, addNextInQueue(state, action: PayloadAction) { state.entries.splice(state.currentIndex + 1, 0, action.payload); }, playNow(state, action: PayloadAction) { const insertAt = state.currentIndex + 1; state.entries.splice(insertAt, 0, action.payload); state.currentIndex = insertAt; }, removeFromQueue(state, action: PayloadAction) { state.entries.splice(action.payload, 1); if (action.payload < state.currentIndex) state.currentIndex--; }, moveInQueue(state, action: PayloadAction<{ from: number; to: number }>) { const { from, to } = action.payload; const [entry] = state.entries.splice(from, 1); state.entries.splice(to, 0, entry); if (state.currentIndex === from) state.currentIndex = to; else if (from < state.currentIndex && to >= state.currentIndex) state.currentIndex--; else if (from > state.currentIndex && to <= state.currentIndex) state.currentIndex++; }, goToIndex(state, action: PayloadAction) { state.currentIndex = action.payload; }, nextTrack(state) { if (state.shuffle && state.entries.length > 1) { let next = state.currentIndex; while (next === state.currentIndex) { next = Math.floor(Math.random() * state.entries.length); } state.currentIndex = next; } else if (state.currentIndex < state.entries.length - 1) { state.currentIndex++; } }, prevTrack(state) { if (state.currentIndex > 0) state.currentIndex--; }, clearQueue(state) { state.entries = []; state.currentIndex = -1; }, toggleShuffle(state) { state.shuffle = !state.shuffle; }, toggleLoop(state) { state.loop = !state.loop; }, }, }); export const { setQueue, addToQueue, addNextInQueue, playNow, removeFromQueue, moveInQueue, goToIndex, nextTrack, prevTrack, clearQueue, toggleShuffle, toggleLoop, } = queueSlice.actions; export default queueSlice.reducer;