`PlaylistAPI` provides playlist loading, navigation, and item management for a `PlayerAPI` instance.
Playlist implementations are exposed by plugins.

## Playlist modes

`HLSPlugin` currently provides two modes.

### Native Queue

Uses `AVQueuePlayer` internally.
The queue keeps upcoming items prepared and handles transitions between items.

### Item Replace

Uses a single player item pipeline.
When the active index changes, the current item is replaced with the selected item.

## Basic usage

Enable `HLSPlugin` during SDK setup:

```swift
import PRESTOplay
import CastlabsApple

let setupError = PRESTOplaySDK.shared.setup("LICENSE", [HLSPlugin()])
```

Create a player, create a playlist, and load items:

```swift
let player = PRESTOplaySDK.shared.player()
let playlist = PRESTOplaySDK.shared.playlist(for: player, mode: .nativeQueue)!

let items = [
    PlayerConfiguration(with: URL(string: "https://example.com/stream-1.m3u8")!),
    PlayerConfiguration(with: URL(string: "https://example.com/stream-2.m3u8")!)
]

playlist.load(items: items)

playlist.onItemChange = {
    print("Current index: \(playlist.getCurrentItemIndex())")
}

playlist.onPlaylistEnded = {
    print("Playlist ended")
}

playlist.nextItem()
playlist.previousItem()
playlist.playItem(at: 1)

let item3 = PlayerConfiguration(with: URL(string: "https://example.com/stream-3.m3u8")!)
playlist.addItem(item3)
playlist.removeItem(at: 0)
```

Create a playlist without passing `mode` to use the default `PlaylistMode.playerRecreate`:

```swift
let defaultPlaylist = PRESTOplaySDK.shared.playlist(for: player)
```

For `PlaylistMode.nativeQueue`, configure loop behavior with `loopList`:

```swift
let loopingPlaylist = PRESTOplaySDK.shared.playlist(
    for: player,
    mode: .nativeQueue,
    loopList: true
)
```

`loopList` defaults to `true`. When `false`, navigation stops at the queue boundaries.
`playItem(at:)` keeps the current item unchanged when the index is out of bounds.
