"""How long does one question from ask.py take through the model's PUBLIC entry point?

    python public_timing.py

ask.py opens a new connection for every question, so each one pays for the handshake.
This sends ask.py's three questions four times, each on a new connection, and prints
the middle, fastest and slowest time.

On our own network the name leads straight to the computer, which is faster and proves
nothing about the public side. So the name is looked up at a public DNS server (8.8.8.8)
and curl is pinned to that address with --resolve. From anywhere else this changes
nothing. It needs curl and nslookup.
"""
import json
import pathlib
import re
import statistics
import subprocess
import sys
import tempfile
import urllib.parse

ASSETS = pathlib.Path(__file__).resolve().parent.parent      # the tutorial's files: one folder up from checks/
ROUNDS = 4


def public_address(host):
    """One of the name's public IPv4 addresses, as a stranger's computer would get it."""
    found = subprocess.run(["nslookup", "-type=A", host, "8.8.8.8"], capture_output=True, text=True).stdout
    answer = found.split("Name:")[-1]           # the lines before "Name:" are the DNS server's own
    return re.findall(r"\d+\.\d+\.\d+\.\d+", answer)[0]


def main():
    sys.path.insert(0, str(ASSETS))
    import ask
    parts = urllib.parse.urlsplit(ask.MODEL)
    port = parts.port or 443
    entry = public_address(parts.hostname)
    folder = pathlib.Path(tempfile.mkdtemp())
    times = []
    for round_number in range(ROUNDS):
        for sees in ask.SEES:
            question = {"type": "choice", "instructions": "What should you do right now?", "criteria": ask.MOVES}
            message = {"state": ask.WHO + " Rules: " + ask.RULES + "\n\nSituation: " + sees,
                       "questions": {"move": question}}
            (folder / "message.json").write_text(json.dumps(message), encoding="utf-8")
            done = subprocess.run(
                ["curl", "-s", "-m", "40", "--resolve", f"{parts.hostname}:{port}:{entry}",
                 "-o", str(folder / "answer.json"), "-w", "%{http_code} %{remote_ip} %{time_total}",
                 "-H", "Content-Type: application/json", "--data-binary", "@" + str(folder / "message.json"),
                 ask.MODEL], capture_output=True, text=True)
            code, far_address, seconds = done.stdout.split()
            answer = json.loads((folder / "answer.json").read_text(encoding="utf-8"))
            times.append(float(seconds))
            if round_number == 0:
                print(f"  {code} via {far_address}  {float(seconds):.2f} s  {answer['answers']['move']['choice']:5}  {sees}")
    print(f"{len(times)} questions, each on a new connection: middle {statistics.median(times):.2f} s, "
          f"fastest {min(times):.2f} s, slowest {max(times):.2f} s")
    return 0


if __name__ == "__main__":
    sys.exit(main())
