from __future__ import annotations

import os
import subprocess
import time
from pathlib import Path

import pytest


class Steve:
    dev_name: str | None = None
    dev_path: str | None = None
    subprocess: subprocess.Popen | None = None
    retval: int | None = None

    def start(self, args: list[str]) -> None:
        self.dev_name = f"steve.test/{os.getpid()}"
        self.dev_path = Path(f"/dev/{self.dev_name}")
        self.subprocess = subprocess.Popen(
            [os.environ.get("STEVE", "steve"), "--dev-name", self.dev_name, *args]
        )

        # wait for device to appear
        for attempt in range(15):
            if self.dev_path.exists():
                break
            if self.subprocess.poll() is not None:
                raise RuntimeError(f"Steve exited with status {self.subprocess.returncode}")
            time.sleep(0.1 * attempt)
        else:
            raise RuntimeError("Steve failed to start")

    def terminate(self) -> None:
        if self.subprocess is not None:
            self.subprocess.terminate()
            self.retval = self.subprocess.wait()


@pytest.fixture
def steve() -> Steve:
    steve = Steve()
    yield steve
    steve.terminate()
