#!/usr/bin/env python3
"""Measure real scan time against C3 (192.168.0.240) using EXACT gateway batching logic."""
import json
import time
import sys
from pathlib import Path

from pymodbus.client import ModbusTcpClient

REG_MAP = Path(__file__).parent.parent / "docs" / "register-map-c3.json"
HOST = "192.168.0.240"
PORT = 502
RUNS = 5

def load_regs():
    with open(REG_MAP) as f:
        return json.load(f)["registers"]

def build_batches(regs):
    """
    EXACT gateway logic (gateway.cpp:123-173):
    1. Sort registers by address
    2. For each batch: start_addr = first register's addr
    3. Collect all registers where: addr + count - batch_start <= 120
    4. Read count = last.addr + last.count - batch_start
    """
    sorted_regs = sorted(regs, key=lambda r: r["addr"])
    batches = []
    MAX_BATCH = 120
    i = 0
    while i < len(sorted_regs):
        batch_start = sorted_regs[i]["addr"]
        j = i
        while j < len(sorted_regs):
            e = sorted_regs[j]
            if e["addr"] + e["count"] - batch_start > MAX_BATCH:
                break
            j += 1
        # j-1 is the last register in this batch
        last = sorted_regs[j - 1]
        read_count = last["addr"] + last["count"] - batch_start
        batches.append((batch_start, read_count))
        i = j
    return batches

def main():
    regs = load_regs()
    batches = build_batches(regs)

    total_regs = len(regs)
    total_words = sum(r["count"] for r in regs)
    print(f"Registers: {total_regs}, Total words: {total_words}, Batches: {len(batches)}")
    print(f"Target: {HOST}:{PORT}")
    print()

    client = ModbusTcpClient(HOST, port=PORT, timeout=5)
    if not client.connect():
        print("ERROR: connection failed"); sys.exit(1)

    times = []
    for run in range(1, RUNS + 1):
        t0 = time.perf_counter()
        errors = 0
        for i, (addr, count) in enumerate(batches):
            resp = client.read_holding_registers(addr, count=count)
            if resp.isError():
                errors += 1

        elapsed = (time.perf_counter() - t0) * 1000
        times.append(elapsed)
        print(f"run{run}: {elapsed:.1f} ms  (batches {len(batches)}, errors {errors})")

    client.close()

    times.sort()
    print(f"\n---")
    print(f"Min:  {times[0]:.1f} ms")
    print(f"Max:  {times[-1]:.1f} ms")
    print(f"Avg:  {sum(times)/len(times):.1f} ms")
    print(f"Median: {times[len(times)//2]:.1f} ms")

if __name__ == "__main__":
    main()
