//
// LiveRunState.swift
// Workouts
//
// Copyright 2025 Rouslan Zenetl. All Rights Reserved.
//

import Foundation
import Observation

/// Phone-side holder for the *ephemeral* live-run frames the watch broadcasts while it drives
/// an exercise (see `LiveProgress`). The mirror UI observes this; nothing here is persisted.
///
/// Phase 1 is watch-drives / phone-mirrors, so this is read-only state fed by the connectivity
/// bridge — the phone never sends back, which is why there's no echo loop to guard against yet.
@Observable
@MainActor
final class LiveRunState {
    /// The latest frame from the driving device, or `nil` when no run is being mirrored.
    private(set) var current: LiveProgress?

    /// A log the user manually closed the mirror for; suppressed until that run ends.
    private var mutedLogID: String?

    /// The run currently open in a non-cover driver on *this* device (its in-list/navigated
    /// `ExerciseProgressView`). When an incoming frame is for that run, the device follows it
    /// inline in that driver, so the mirror cover doesn't stack on top of a run already open.
    var navigatedRunID: String?

    /// The frame to actually present as a cover: the latest frame, unless the user dismissed it
    /// or already has that run open inline.
    var presentable: LiveProgress? {
        guard let c = current, c.logID != mutedLogID, c.logID != navigatedRunID else { return nil }
        return c
    }

    /// Apply an incoming frame, dropping a stale (or redelivered) one for the same run.
    func apply(_ frame: LiveProgress) {
        if let c = current, c.logID == frame.logID, !frame.isNewer(than: c) { return }
        current = frame
    }

    /// The driver left the run (cancel / done / navigated away) — stop mirroring it.
    func end(logID: String) {
        if current?.logID == logID { current = nil }
        if mutedLogID == logID { mutedLogID = nil }
    }

    /// The user dismissed the mirror; don't re-present this run until it ends.
    func mute() {
        mutedLogID = current?.logID
    }
}
