package link.roadio.riff.player.library import link.roadio.riff.indexer.core.media.MediaId import link.roadio.riff.player.core.selection.AiFeaturePoint import link.roadio.riff.player.storage.StoredAudiobookOverride import link.roadio.riff.player.storage.StoredContentMode import link.roadio.riff.ui.BrowserItem import link.roadio.riff.ui.PlaybackSourceRef import link.roadio.riff.ui.TocChapter data class PlayerLibraryProjection( val contentMode: StoredContentMode = StoredContentMode.MUSIC, val audiobookOverrides: Map = emptyMap(), ) data class PlayerLibraryModel( val root: BrowserItem, val tracks: List, val retainedTracks: List = tracks, val playbackSourcesByMediaId: Map>, val generation: Long, val mediaIds: Set, val mediaAliases: Map = emptyMap(), val aiFeaturesByMediaId: Map = emptyMap(), val pteByMediaId: Map = emptyMap(), val topInferredGenreByMediaId: Map = emptyMap(), val augmentationGeneration: Long? = null, /** Automatic book membership supplied by the Indexer projection. */ val audiobookMediaIds: Set = emptySet(), val effectiveBookMediaIds: Set = emptySet(), val tocMarkersByBindingId: Map> = emptyMap(), val tocChaptersByBindingId: Map> = emptyMap(), val projection: PlayerLibraryProjection = PlayerLibraryProjection(), val catalogsReady: Boolean = false, /** Canonical -18 LUFS ReplayGain data keyed by Media.ID. */ val replayGainByMediaId: Map = emptyMap(), val replayGainGeneration: Long? = null, ) { val tracksByMediaId: Map by lazy(LazyThreadSafetyMode.PUBLICATION) { val actual = tracks.associateBy { requireNotNull(it.mediaId) } actual + mediaAliases.mapNotNull { (alias, canonical) -> actual[canonical]?.let { alias to it } } } } data class PlayerLibraryModels( val music: PlayerLibraryModel, val audiobook: PlayerLibraryModel, ) { fun forMode(mode: StoredContentMode): PlayerLibraryModel = if (mode == StoredContentMode.AUDIOBOOK) audiobook else music }