import json
import subprocess


class Tunnel:
    """Start an Internet-accessible tunnel to the Agent running at the given host:port.

    Returns the public URL on which the Agent can be contacted.

    Shuts down the tunnel when the context manager exits.
    """

    def __init__(self, host: str, port: int):
        self._host = host
        self._port = port

    def __enter__(self):
        self._proc = subprocess.Popen(
            [
                "ssh",
                "-R",
                f"80:localhost:{self._port}",
                "-o",
                "StrictHostKeyChecking=accept-new",
                "nokey@localhost.run",
                "--",
                "--output=json",
            ],
            stdin=subprocess.DEVNULL,
            stdout=subprocess.PIPE,
            stderr=subprocess.DEVNULL,
            encoding="utf-8",
        )
        assert self._proc.stdout is not None
        while True:
            line = self._proc.stdout.readline()
            if not line:
                break
            try:
                parsed = json.loads(line)
                if "address" in parsed:
                    return f"https://{parsed['address']}"
            except:
                pass

    def __exit__(self, exc_type, exc_val, exc_tb):
        self._proc.terminate()
        self._proc.wait()
