use std::convert::Infallible;
use chrono::{DateTime, Utc};
use lunar_lib::{
formatter::{FormatTable, Taggable},
id::Id,
paths::sys::sanitize_str,
};
use serde::{Deserialize, Serialize};
use crate::library::{
album::Album,
artist::Artist,
image_art::ImageArt,
track::{Track, lyric_data::LyricData},
};
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
pub struct TrackMeta {
pub album: Option<Id<Album>>,
pub artists: Vec<Id<Artist>>,
pub date: Option<DateTime<Utc>>,
pub genre: Vec<String>,
pub lyric_data: Option<LyricData>,
pub art: Option<Id<ImageArt>>,
pub other: Vec<(String, String)>,
pub title: Option<String>,
}
impl TrackMeta {
#[must_use]
pub fn new() -> Self {
Self {
title: None,
artists: Vec::new(),
album: None,
date: None,
genre: Vec::new(),
art: None,
lyric_data: None,
other: Vec::new(),
}
}
#[must_use]
pub fn artists(&self) -> &[Id<Artist>] {
&self.artists
}
#[must_use]
pub fn album(&self) -> Option<Id<Album>> {
self.album
}
#[must_use]
pub fn safe_title(&self) -> &str {
self.title.as_deref().unwrap_or(Track::UNKNOWN)
}
}
impl Taggable for TrackMeta {
type Err = Infallible;
fn fill_table(&self, table: &mut FormatTable) -> Result<(), Self::Err> {
if let Some(value) = self.date {
table.add_entry("date", value.to_string());
}
if let Some(value) = &self.title {
table.add_entry("title", sanitize_str(value));
}
if !self.genre.is_empty() {
table.add_entry("genre", sanitize_str(self.genre.join(";")));
}
Ok(())
}
}