//
// Play queue with optional shuffle.
//
// Shuffle mode cycles: OFF → ALL → FAVOURITES → OFF.
// In shuffle modes, queue_next/prev walk a Fisher-Yates permutation of track
// indices rather than sequential order. FAVOURITES filters the pool to tracks
// where is_favourite is true.
//

Shuffle_Mode :: enum {
    OFF;
    ALL;
    FAVOURITES;
}

Queue :: struct {
    tracks:        [..] Track;
    current:       int = -1;

    shuffle_mode:  Shuffle_Mode;
    shuffle_order: [..] int;   // permuted indices into tracks[]
    shuffle_pos:   int = -1;   // current position within shuffle_order
}

queue: Queue;

queue_clear :: () {
    array_reset(*queue.tracks);
    array_reset(*queue.shuffle_order);
    queue.current     = -1;
    queue.shuffle_pos = -1;
}

queue_add :: (track: Track) {
    array_add(*queue.tracks, track);
}

// Build a fresh permutation from the current track list. Call after all
// queue_adds are done, and whenever shuffle mode changes.
queue_rebuild_shuffle :: () {
    array_reset(*queue.shuffle_order);
    if queue.shuffle_mode == .OFF  return;

    for i: 0..queue.tracks.count-1 {
        if queue.shuffle_mode == .FAVOURITES && !queue.tracks[i].is_favourite  continue;
        array_add(*queue.shuffle_order, i);
    }

    // Fisher-Yates — must use while loop; Jai's a..b range goes forward when
    // a < b, so `for i: n-1..1` would iterate upward and crash on n=1.
    i := queue.shuffle_order.count - 1;
    while i > 0 {
        j := cast(int)(random_get() % cast(u64)(i + 1));
        tmp                    := queue.shuffle_order[i];
        queue.shuffle_order[i]  = queue.shuffle_order[j];
        queue.shuffle_order[j]  = tmp;
        i -= 1;
    }

    // Put the current track at position 0 so << works sensibly immediately.
    if queue.current >= 0 {
        for i: 0..queue.shuffle_order.count-1 {
            if queue.shuffle_order[i] == queue.current {
                tmp                    := queue.shuffle_order[0];
                queue.shuffle_order[0]  = queue.shuffle_order[i];
                queue.shuffle_order[i]  = tmp;
                break;
            }
        }
    }
    queue.shuffle_pos = 0;
}

queue_set_shuffle :: (mode: Shuffle_Mode) {
    if queue.shuffle_mode == mode  return;
    queue.shuffle_mode = mode;
    queue_rebuild_shuffle();
}

queue_play_index :: (index: int) -> bool {
    if index < 0 || index >= queue.tracks.count  return false;
    queue.current = index;
    if queue.shuffle_mode != .OFF {
        for i: 0..queue.shuffle_order.count-1 {
            if queue.shuffle_order[i] == index {
                queue.shuffle_pos = i;
                break;
            }
        }
    }
    audio_play_track(queue.tracks[index]);
    return true;
}

queue_next :: () -> bool {
    if queue.shuffle_mode != .OFF && queue.shuffle_order.count > 0 {
        next := queue.shuffle_pos + 1;
        if next >= queue.shuffle_order.count  return false;
        queue.shuffle_pos = next;
        queue.current     = queue.shuffle_order[next];
        audio_play_track(queue.tracks[queue.current]);
        return true;
    }
    return queue_play_index(queue.current + 1);
}

queue_prev :: () -> bool {
    if queue.shuffle_mode != .OFF && queue.shuffle_order.count > 0 {
        prev := queue.shuffle_pos - 1;
        if prev < 0  return false;
        queue.shuffle_pos = prev;
        queue.current     = queue.shuffle_order[prev];
        audio_play_track(queue.tracks[queue.current]);
        return true;
    }
    return queue_play_index(queue.current - 1);
}
