"""Cross-process media ownership for Linux robot appliances."""
from __future__ import annotations

import os
import sys
import time
from pathlib import Path
from typing import Optional


class MediaLock:
    def __init__(self, kind: str, timeout: float = 5.0):
        self.kind = kind
        self.timeout = timeout
        self.fd: Optional[int] = None

    def acquire(self) -> "MediaLock":
        if not sys.platform.startswith("linux"):
            return self
        import fcntl

        lock_dir = Path("/run/lock") if os.access("/run/lock", os.W_OK) else Path("/tmp")
        path = lock_dir / f"robopark-{self.kind}.lock"
        self.fd = os.open(path, os.O_CREAT | os.O_RDWR, 0o660)
        deadline = time.monotonic() + self.timeout
        while True:
            try:
                fcntl.flock(self.fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
                os.ftruncate(self.fd, 0)
                os.write(self.fd, f"{os.getpid()}\n".encode("ascii"))
                return self
            except BlockingIOError:
                if time.monotonic() >= deadline:
                    self.release()
                    raise TimeoutError(f"{self.kind} is owned by another RoboPark media process")
                time.sleep(0.05)

    def release(self) -> None:
        if self.fd is None:
            return
        try:
            if sys.platform.startswith("linux"):
                import fcntl
                fcntl.flock(self.fd, fcntl.LOCK_UN)
        finally:
            os.close(self.fd)
            self.fd = None

    def __enter__(self) -> "MediaLock":
        return self.acquire()

    def __exit__(self, exc_type, exc, traceback) -> None:
        self.release()


def media_lock(kind: str, timeout: float = 5.0) -> MediaLock:
    return MediaLock(kind, timeout)
