import html
import json
import os
import re
import socket
import time
import urllib.request

BRIDGE = os.environ.get("GS10_WEB", "http://127.0.0.1:8253")
DASH = os.environ.get("DASH_URL", "https://rtk.pavlokostiuk.cloud/api/gs10")
TOKEN = os.environ["DASH_TOKEN"]
INTERVAL = int(os.environ.get("INTERVAL", "20"))
PAGES = {
    "battery": "/status/status_MemoryBattery.lsp",
    "position": "/status/status_Position.lsp",
    "rtk": "/status/status_RTK_Base1.lsp",
}
TRACKING = {"GPS": "/status/status_Tracking_Gps.lsp", "GLONASS": "/status/status_Tracking_Glonass.lsp"}
SAT_FIELDS = ["sat", "elevation", "azimuth", "snr_l1", "snr_l2p", "snr_l2c", "health"]


def log(*a):
    print(time.strftime("%H:%M:%S"), *a, flush=True)


def text(v):
    return re.sub(r"\s+", " ", html.unescape(re.sub(r"<[^>]+>", "", v))).strip()


def rows(page):
    return [
        [(re.search(r'class="([^"]+)"', attrs).group(1) if 'class="' in attrs else "", text(v)) for attrs, v in re.findall(r"(?s)<t[dh]([^>]*)>(.*?)</t[dh]>", r)]
        for r in re.findall(r"(?s)<tr[^>]*>(.*?)</tr>", page)
    ]


def fields(page):
    pairs = [(cells[0][1].rstrip(":"), [v for _, v in cells[1:]]) for cells in rows(page) if cells and cells[0][0] == "tdl"]
    return dict(reversed(pairs))


def satellites(page):
    return [
        dict(zip(SAT_FIELDS, [v for _, v in cells]))
        for cells in rows(page)
        if len(cells) == 7 and all(c == "tdm_text_centered" for c, _ in cells) and cells[0][1] not in ("", "--")
    ]


def fetch(path):
    with urllib.request.urlopen(BRIDGE + path, timeout=30) as r:
        return r.read().decode("utf-8", "replace")


def report():
    try:
        return {
            "bridge": True,
            "pages": {name: fields(fetch(path)) for name, path in PAGES.items()},
            "sats": {system: satellites(fetch(path)) for system, path in TRACKING.items()},
            "pi": socket.gethostname(),
        }
    except OSError as e:
        return {"bridge": False, "error": str(e), "pi": socket.gethostname()}


def push(data):
    req = urllib.request.Request(DASH, data=json.dumps(data).encode(), method="POST", headers={"Content-Type": "application/json", "Authorization": f"Bearer {TOKEN}"})
    with urllib.request.urlopen(req, timeout=20) as r:
        return r.status


if __name__ == "__main__":
    while True:
        data = report()
        try:
            log("pushed", push(data), "bridge" if data["bridge"] else f"bridge down: {data['error']}")
        except OSError as e:
            log("push failed:", e)
        time.sleep(INTERVAL)
