use lunar_lib::database::{
    CompareAndSwapTransaction, DatabaseEntry, Deleteable, Entry, IdExt, TransactionError,
    caching::Cacheable,
};

use crate::{
    database::{Library, Searchable, album_remove_track, artist_remove_track},
    library::track::Track,
};

impl DatabaseEntry for Track {
    type DbInner = Library;

    const VERSION_NUMBER: u32 = 1;
    const TREE_NAME: &str = "track";
}

impl Cacheable for Track {}

impl Deleteable for Track {
    fn unlink_references(
        track: Entry<Self>,
        cas_tx: &mut CompareAndSwapTransaction<Self::DbInner>,
    ) -> Result<(), TransactionError> {
        if let Some(album) = track.metadata.album {
            album.tx_fetch_and_update(
                |old, _| {
                    let mut album = old.expect("Dangling ref");
                    album_remove_track(&mut album, track.id());
                    Ok(Some(album))
                },
                cas_tx,
            )?;
        }

        track.metadata.artists().tx_fetch_and_update(
            |old| {
                let mut artist = old.expect("Dangling ref");
                artist_remove_track(&mut artist, track.id());
                Some(artist)
            },
            cas_tx,
        )?;

        Ok(())
    }
}

impl Searchable for Track {
    const SEARCH_INDEX: &'static str = "track_search";

    fn search_name(&self) -> Option<&str> {
        self.metadata.title.as_deref()
    }
}
