"""CDP driver for OWA chrome, port 9224."""
import json, time, urllib.request
import websocket

CDP_HTTP = "http://localhost:9224"

def http_get(path):
    with urllib.request.urlopen(CDP_HTTP + path, timeout=10) as r:
        return json.loads(r.read().decode())

def list_pages():
    return [t for t in http_get("/json") if t.get("type") == "page"]

def find_target(url_sub=None, want_blank=False):
    pages = list_pages()
    if url_sub:
        for p in pages:
            if url_sub in (p.get("url") or ""):
                return p
    if want_blank:
        for p in pages:
            if (p.get("url") or "") in ("about:blank", ""):
                return p
    return pages[0] if pages else None

def new_target(url="about:blank"):
    return http_get("/json/new?" + url)

class Page:
    def __init__(self, ws_url):
        self.ws = websocket.create_connection(ws_url, timeout=30, max_size=None)
        self._id = 0
    def send(self, method, params=None, timeout=30):
        self._id += 1
        mid = self._id
        self.ws.send(json.dumps({"id": mid, "method": method, "params": params or {}}))
        deadline = time.time() + timeout
        while time.time() < deadline:
            self.ws.settimeout(deadline - time.time())
            try:
                msg = json.loads(self.ws.recv())
            except Exception as e:
                raise RuntimeError("recv failed: %s" % e)
            if msg.get("id") == mid:
                if "error" in msg:
                    raise RuntimeError("CDP error %s: %s" % (method, msg["error"]))
                return msg.get("result", {})
        raise RuntimeError("timeout waiting for %s" % method)
    def enable(self):
        self.send("Page.enable")
        self.send("Runtime.enable")
        self.send("DOM.enable")
    def navigate(self, url):
        return self.send("Page.navigate", {"url": url})
    def eval(self, expr, await_promise=False, timeout=30):
        r = self.send("Runtime.evaluate", {
            "expression": expr,
            "returnByValue": True,
            "awaitPromise": await_promise,
        }, timeout=timeout)
        if "exceptionDetails" in r:
            raise RuntimeError("JS exception: " + json.dumps(r["exceptionDetails"])[:500])
        return r.get("result", {}).get("value")
    def screenshot(self, path):
        r = self.send("Page.captureScreenshot", {"format": "png"}, timeout=30)
        import base64
        with open(path, "wb") as f:
            f.write(base64.b64decode(r["data"]))
        return path
    def close(self):
        try: self.ws.close()
        except Exception: pass

def attach(target):
    return Page(target["webSocketDebuggerUrl"])
