use std::sync::Arc;
use lunar_lib::database::{DatabaseEntry, EntryIdIteratorExt, TransactionError};
use crate::{
database::LibraryDb,
library::artist::{Artist, ArtistId},
};
pub trait ArtistGroup {
fn artist_ids(&self) -> &[ArtistId];
fn artists(&self, db: &LibraryDb) -> Result<Vec<Artist>, TransactionError>;
fn artists_cache(&self, db: &LibraryDb) -> Result<Vec<Arc<Artist>>, TransactionError>;
fn main_artist_id(&self) -> Option<ArtistId>;
fn main_artist(&self, db: &LibraryDb) -> Result<Option<Artist>, TransactionError>;
fn featuring_artist_ids(&self) -> &[ArtistId];
fn featuring_artists(&self, db: &LibraryDb) -> Result<Vec<Artist>, TransactionError>;
fn add_artist(&mut self, artist: ArtistId);
fn add_artists(&mut self, artists: impl IntoIterator<Item = ArtistId>);
fn remove_artist(&mut self, artist: ArtistId);
fn remove_artists(&mut self, artists: impl IntoIterator<Item = ArtistId>);
}
impl ArtistGroup for Vec<ArtistId> {
fn artist_ids(&self) -> &[ArtistId] {
self
}
fn artists(&self, db: &LibraryDb) -> Result<Vec<Artist>, TransactionError> {
self.iter().copied().db_get_batch(db)
}
fn artists_cache(&self, db: &LibraryDb) -> Result<Vec<Arc<Artist>>, TransactionError> {
self.iter().copied().cache_get_batch(db)
}
fn main_artist_id(&self) -> Option<ArtistId> {
self.first().copied()
}
fn main_artist(&self, db: &LibraryDb) -> Result<Option<Artist>, TransactionError> {
if let Some(first) = self.first() {
let artist = Artist::db_get(*first, db)?
.expect("ArtistGroup main artist did not exist in the database");
Ok(Some(artist))
} else {
Ok(None)
}
}
fn featuring_artist_ids(&self) -> &[ArtistId] {
self.get(1..).unwrap_or_default()
}
fn featuring_artists(&self, db: &LibraryDb) -> Result<Vec<Artist>, TransactionError> {
self.featuring_artist_ids().iter().copied().db_get_batch(db)
}
fn add_artist(&mut self, artist: ArtistId) {
if !self.contains(&artist) {
self.push(artist);
}
}
fn add_artists(&mut self, artists: impl IntoIterator<Item = ArtistId>) {
artists.into_iter().for_each(|artist| {
self.add_artist(artist);
});
}
fn remove_artist(&mut self, artist: ArtistId) {
self.retain(|a| *a != artist);
}
fn remove_artists(&mut self, artists: impl IntoIterator<Item = ArtistId>) {
let artists: Vec<ArtistId> = artists.into_iter().collect();
self.retain(|a| !artists.contains(a));
}
}