use std::collections::HashMap;
use std::path::PathBuf;
use reader::PlaylistStore;
use reader::models::{ArtistImageRef, Playlist, PlaylistFolder};
use sqlx::SqlitePool;
use crate::{ArtistImages, DbError, QueueSnapshot, Source};
pub async fn artist_images(pool: &SqlitePool) -> Result<ArtistImages, DbError> {
let rows = sqlx::query!("SELECT artist_norm, kind, image_ref FROM artist_images")
.fetch_all(pool)
.await?;
let mut overrides = HashMap::new();
let mut photos: HashMap<String, ArtistImageRef> = HashMap::new();
for r in rows {
match r.kind.as_str() {
"custom" => {
overrides.insert(r.artist_norm, PathBuf::from(r.image_ref));
}
"server" => {
photos.insert(r.artist_norm, ArtistImageRef::Remote(r.image_ref));
}
_ => {
photos
.entry(r.artist_norm)
.or_insert_with(|| ArtistImageRef::Local(PathBuf::from(r.image_ref)));
}
}
}
Ok((overrides, photos))
}
pub async fn load_playlists(pool: &SqlitePool, source: &Source) -> Result<PlaylistStore, DbError> {
let src = source.as_str();
let rows = sqlx::query!(
"SELECT rowid_pk, source_pl_id, name, cover_path, image_tag \
FROM playlists WHERE source = ?1 AND source_pl_id != 'LM' ORDER BY position",
src
)
.fetch_all(pool)
.await?;
let mut playlists = Vec::new();
for r in rows {
let tracks: Vec<String> = sqlx::query_scalar!(
"SELECT track_ref FROM playlist_tracks WHERE playlist_pk = ?1 ORDER BY position",
r.rowid_pk
)
.fetch_all(pool)
.await?;
playlists.push(Playlist {
id: r.source_pl_id,
name: r.name,
tracks,
image_tag: r.image_tag,
cover_path: r.cover_path.map(PathBuf::from),
});
}
let folder_rows = sqlx::query!("SELECT id, name FROM folders")
.fetch_all(pool)
.await?;
let mut folders = Vec::new();
for f in folder_rows {
let playlist_ids: Vec<String> = sqlx::query_scalar!(
"SELECT playlist_ref FROM folder_playlists WHERE folder_id = ?1 ORDER BY position",
f.id
)
.fetch_all(pool)
.await?;
folders.push(PlaylistFolder {
id: f.id,
name: f.name,
playlist_ids,
});
}
Ok(PlaylistStore { playlists, folders })
}
pub async fn load_queue(pool: &SqlitePool) -> Result<QueueSnapshot, DbError> {
let row = sqlx::query!(
"SELECT version, queue_json, current_queue_index, progress_secs, \
shuffle_order_json, shuffle_enabled \
FROM queue_state WHERE id = 1"
)
.fetch_optional(pool)
.await?;
let Some(row) = row else {
return Ok(QueueSnapshot::default());
};
Ok(QueueSnapshot {
version: row.version.clamp(0, u8::MAX as i64) as u8,
queue: serde_json::from_str(&row.queue_json).unwrap_or_default(),
current_queue_index: row.current_queue_index.max(0) as usize,
progress_secs: row.progress_secs.max(0) as u64,
shuffle_order: serde_json::from_str(&row.shuffle_order_json).unwrap_or_default(),
shuffle_enabled: row.shuffle_enabled != 0,
})
}