"""Per-session sensor value overrides (replacement and/or offset)."""

from __future__ import annotations


class SensorEditor:
    def __init__(self) -> None:
        self._replacements: dict[int, float] = {}
        self._offsets: dict[int, float] = {}


    def set_replacement(self, index: int, value: float) -> None:
        """Force sensor `index` to read `value` for every frame this session."""
        self._replacements[index] = value

    def set_offset(self, index: int, value: float) -> None:
        """Shift sensor `index` by `delta` (applied after any replacement)."""
        self._offsets[index] = value

    def clear(self, index: int | None = None) -> None:
        """Remove overrides. Pass an index to clear one sensor; omit to clear all."""
        if index is None:
            self._replacements.clear()
            self._offsets.clear()
        else:
            self._replacements.pop(index, None)
            self._offsets.pop(index, None)
    def has_overrides(self) -> bool:
        return bool(self._replacements or self._offsets)

    def replaced_indices(self) -> set[int]:
        """Sensors whose value is a replacement (offsets don't count — an
        offset sensor still reads from its physical location)."""
        return set(self._replacements)

    def active_indices(self) -> list[int]:
        """Return sorted sensor indices that have any override."""
        return sorted(set(self._replacements) | set(self._offsets))


    def apply(self, values: list[float]) -> list[float]:
        """Return a new list wit all overrides applied (original unchanged)"""
        if not self.has_overrides():
            return list(values)
        result = list(values)
        for i in range(len(result)):
            v = result[i]
            if i in self._replacements:
                v = self._replacements[i]
            if i in self._offsets:
                v += self._offsets[i]
            result[i] = v
        return result
