package ca.ksamad.encore.mpd

/**
 * The parsed result of a single successful command: the ordered `key: value` lines the server sent
 * before its `OK`, plus an optional [binary] payload for commands like `albumart`/`readpicture`.
 *
 * Order is preserved because several commands (e.g. `playlistinfo`, `lsinfo`) return repeated
 * blocks that are only separable by position — a new object begins each time a delimiting key such
 * as `file` reappears. Use [split] to chop such a response into per-object maps.
 */
class MpdResponse(
    val values: List<Pair<String, String>>,
    val binary: ByteArray? = null,
) {
    /** First value for [key], or `null` if absent. */
    operator fun get(key: String): String? = values.firstOrNull { it.first == key }?.second

    /** All values for [key], in order. */
    fun getAll(key: String): List<String> = values.filter { it.first == key }.map { it.second }

    /**
     * Flatten to a map of first-seen values. Safe for commands whose keys are unique (`status`,
     * `currentsong`, `stats`); lossy for repeated blocks — use [split] there instead.
     */
    fun toMap(): Map<String, String> {
        val out = LinkedHashMap<String, String>(values.size)
        for ((k, v) in values) out.putIfAbsent(k, v)
        return out
    }

    /**
     * Split a multi-object response into one map per object. A new object starts at every
     * occurrence of [delimiter] (default `file`, the first key MPD emits for a song/file entry).
     * Lines before the first delimiter are ignored.
     */
    fun split(delimiter: String = "file"): List<Map<String, String>> {
        val result = ArrayList<Map<String, String>>()
        var current: LinkedHashMap<String, String>? = null
        for ((k, v) in values) {
            if (k == delimiter) {
                current = LinkedHashMap()
                result.add(current)
            }
            current?.putIfAbsent(k, v)
        }
        return result
    }
}
