"""Observe original body queries on the selected ship's game thread; send no inputs."""
import argparse
import hashlib
import json
import pathlib
import time
import frida

p = argparse.ArgumentParser(description=__doc__)
p.add_argument('--pid', type=int, required=True)
p.add_argument('--profile', type=pathlib.Path, required=True)
p.add_argument('--snapshot', type=pathlib.Path, required=True)
p.add_argument('--thread', type=int, required=True)
p.add_argument('--output', type=pathlib.Path, required=True)
p.add_argument('--seconds', type=int, default=12, choices=range(5,61))
a = p.parse_args()
profile = json.loads(a.profile.read_text(encoding='utf-8-sig'))
snapshot = json.loads(a.snapshot.read_text(encoding='utf-8-sig'))
if snapshot['pid'] != a.pid or snapshot['gameSha256'] != profile['sha256'] or hashlib.sha256(pathlib.Path(profile['image']).read_bytes()).hexdigest() != profile['sha256']:
    raise SystemExit('Selected process/build does not match the observation snapshot')
source = 'const PROFILE=' + json.dumps(profile) + ';const SNAPSHOT=' + json.dumps(snapshot) + ';const THREAD=' + str(a.thread) + ';\n' + pathlib.Path(__file__).with_name('navigation-geometry-probe.js').read_text(encoding='utf-8')
a.output.parent.mkdir(parents=True, exist_ok=True)
counts = {}
errors = []
with a.output.open('x', encoding='utf-8') as out:
    session = frida.attach(a.pid)
    try:
        script = session.create_script(source)
        def message(m, data):
            row = m.get('payload') if m['type'] == 'send' else {'kind':'error','detail':m}
            out.write(json.dumps(row)+'\n');out.flush()
            counts[row.get('kind','unknown')] = counts.get(row.get('kind','unknown'),0)+1
            if row.get('kind') == 'error': errors.append(row)
        script.on('message', message)
        script.load()
        deadline = time.monotonic() + a.seconds
        while time.monotonic() < deadline and not errors: time.sleep(.1)
        script.unload()
    finally: session.detach()
print(json.dumps({'counts':counts,'errors':errors,'screenUse':False,'flightInputsSent':0,'nativeCalls':'verified read-only getters on original owning thread'}))
