use std::sync::Arc;

use lunar_lib::database::{DatabaseEntry, TransactionError, caching::Cacheable};

use crate::{
    database::{LibraryDb, Resolveable, TRACK_CACHE},
    library::track::{ResolvedTrack, Track, TrackId},
};

impl DatabaseEntry for Track {
    type Id = TrackId;
    type Db = LibraryDb;

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

    fn id(&self) -> TrackId {
        self.id
    }
}

impl Resolveable for Track {
    type Resolved = ResolvedTrack;

    fn resolve(track: Arc<Self>, db: &Self::Db) -> Result<Self::Resolved, TransactionError> {
        let artists = track.metadata().artists_cache(db)?;

        let album = track.metadata().album_cache(db)?;
        let album_artists = album.as_ref().map(|a| a.artists_cache(db)).transpose()?;

        Ok(ResolvedTrack {
            track,
            album,
            album_artists,
            artists,
        })
    }
}

impl Cacheable for Track {
    fn cache() -> &'static std::sync::Mutex<lunar_lib::database::caching::DbCache<Self>> {
        &TRACK_CACHE
    }
}

impl PartialEq for Track {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id
    }
}

impl Eq for Track {}

impl std::hash::Hash for Track {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        state.write(&*self.id);
    }
}
