package ca.ksamad.encore.mpd.model

/**
 * A song/file entry, parsed from the metadata block MPD emits for `currentsong`, `playlistinfo`,
 * `find`, `lsinfo`, etc. [uri] (the `file` key) is the only required field; every tag is optional
 * because the server only sends tags the file actually has.
 *
 * Tags are kept as raw strings — `track`/`disc` can carry values like `"3/12"`, and normalising
 * them is a display concern left to the UI layer.
 */
data class MpdSong(
    val uri: String,
    val title: String?,
    val artist: String?,
    val album: String?,
    val albumArtist: String?,
    val track: String?,
    val disc: String?,
    val date: String?,
    val genre: String?,
    val lastModified: String?, // "Last-Modified" ISO timestamp; used to cache-bust cover art
    val format: String?, // "Format" audio format "samplerate:bits:channels" (from the DB scan)
    val duration: Double?, // from "duration" (fractional) or legacy "Time"
    val pos: Int?, // queue position, present in queue listings
    val id: Int?, // stable queue id, present in queue listings
) {
    companion object {
        /**
         * Parse one song from a metadata map. Returns `null` when there is no `file` key (i.e. this
         * block is not a song — e.g. a `directory` entry in an `lsinfo` listing).
         */
        fun from(values: Map<String, String>): MpdSong? {
            val uri = values["file"] ?: return null
            return MpdSong(
                uri = uri,
                title = values["Title"],
                artist = values["Artist"],
                album = values["Album"],
                albumArtist = values["AlbumArtist"],
                track = values["Track"],
                disc = values["Disc"],
                date = values["Date"],
                genre = values["Genre"],
                lastModified = values["Last-Modified"],
                format = values["Format"],
                duration = values["duration"]?.toDoubleOrNull() ?: values["Time"]?.toDoubleOrNull(),
                pos = values["Pos"]?.toIntOrNull(),
                id = values["Id"]?.toIntOrNull(),
            )
        }
    }
}
