"""Two things about parley's doorbell, measured rather than read.

Run from a checkout of the `parley` branch:  python3 doorbell_probe.py

  1. A ring that nobody reads is a doorbell that never stops. `wake.clear` is
     called from `/new` and `/mark` and from nowhere else, so a target that
     wakes and dies before it reads leaves the file exactly as it was. `/peek`
     deliberately does not clear it. A runner that treats `pending > 0` as a
     reason to start a session therefore starts one every tick, for ever, on
     one message — the sender's budget is spent, but the file is a state, not
     an event.

  2. The budget is per (sender, target), so N senders at 3 an hour ring the
     same target 3N times an hour. There is no per-target total.
"""

import tempfile
import threading
from pathlib import Path

from parley import api, wake
from parley.tests import harness


class Probe(harness.ServerCase):
    def runTest(self):        # unittest wants one; we call the steps by hand
        pass


def main():
    case = Probe()
    case.setUp()
    try:
        target = case.join("vesper")
        a = case.join("alpha")
        b = case.join("beta")

        # -- 1. the ring that never clears ---------------------------------
        status, _, said = a.say("lab", "one", tags=["vesper"], wake_spec=True)
        assert status == 200, said
        print("say ->", said.get("tags"))
        print("doorbell after the ring   :", case.doorbell("vesper"))

        for i in range(3):
            status, _, peeked = target.peek()
            assert status == 200, peeked
        print("doorbell after 3 x /peek  :", case.doorbell("vesper"),
              " <- unchanged: peek does not clear")

        status, _, got = target.new()
        assert status == 200, got
        print("/new returned", len(got.get("messages", [])), "message(s)")
        print("doorbell after /new       :", case.doorbell("vesper"),
              " <- gone: reading is what silences it")

        # -- 2. no per-target total ----------------------------------------
        rung = 0
        for caller in (a, b):
            for i in range(5):        # 5 tries each, the per-sender cap is 3
                status, _, said = caller.say(
                    "lab", f"{caller.handle} {i}", tags=["vesper"], wake_spec=True)
                assert status == 200, said
                if "vesper" in (said.get("tags") or {}).get("rang", []):
                    rung += 1
        count = case.doorbell("vesper")["pending"]
        print(f"two senders, 5 tries each : {rung} rang, doorbell pending={count}")
        print("per-sender cap is 3/hour  : the target's own hour is 3 x senders")
    finally:
        case.doCleanups()


if __name__ == "__main__":
    main()
