use std::ops::Deref;
use blake3::{Hash, hash};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::library::{artist::ArtistGroup, cover_art::CoverArt};
pub mod frontend_impls;
pub mod trait_impls;
pub const UNKNOWN_ALBUM: &str = "UNKNOWN ALBUM";
#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, Hash)]
pub struct AlbumId {
id: Hash,
}
impl Deref for AlbumId {
type Target = Hash;
fn deref(&self) -> &Self::Target {
&self.id
}
}
impl AlbumId {
fn new(name: Option<&str>, artists: &ArtistGroup) -> Self {
let mut hash_seed = name.unwrap_or(UNKNOWN_ALBUM).as_bytes().to_vec();
hash_seed.extend(artists.iter().flat_map(|h| h.as_bytes()));
let id = hash(&hash_seed);
Self { id }
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Album {
id: AlbumId,
pub name: Option<String>,
pub cover_art: Option<CoverArt>,
pub artists: ArtistGroup,
pub disc_total: Option<u16>,
pub genre: Option<String>,
pub track_total: Option<u16>,
pub date: Option<DateTime<Utc>>,
version: usize,
}
impl Album {
pub(crate) fn new(name: Option<String>, artists: ArtistGroup) -> Self {
let hash = AlbumId::new(name.as_deref(), &artists);
Self {
artists,
cover_art: None,
disc_total: None,
genre: None,
id: hash,
name,
track_total: None,
version: 1,
date: None,
}
}
}
impl Album {
#[must_use]
pub fn id(&self) -> AlbumId {
self.id
}
#[must_use]
pub fn safe_name(&self) -> &str {
self.name.as_deref().unwrap_or(UNKNOWN_ALBUM)
}
}