/*
 * SPDX-License-Identifier: GPL-3.0-or-later
 */
package com.runicgateway.app.ui.shard

/**
 * A live board keyed by a stable id: seeded from a snapshot read, then kept current
 * by SSE `*.update` / `*.remove` deltas (PLAN.md §6.2). Insertion order is
 * preserved (a [LinkedHashMap]) so re-seeding is deterministic; callers sort for
 * display. Not thread-safe — mutate it only from the owning ViewModel coroutine.
 */
class LiveBoard<T>(private val idOf: (T) -> String) {
    private val items = LinkedHashMap<String, T>()

    /** Replace the whole board with a fresh snapshot. */
    fun seed(snapshot: List<T>) {
        items.clear()
        for (item in snapshot) items[idOf(item)] = item
    }

    /** Insert or update one entry (a `*.update` frame). */
    fun upsert(item: T) {
        items[idOf(item)] = item
    }

    /** Drop one entry by id (a `*.remove` frame). No-op if absent. */
    fun remove(id: String) {
        items.remove(id)
    }

    /** The current board contents, in insertion order. */
    fun values(): List<T> = items.values.toList()
}
