"""Inspect all-tile transfer gaps and measured boundaries in a rendered profile."""
import collections
import json
import sys
from pathlib import Path
text = Path(sys.argv[1]).read_text()
d = json.JSONDecoder().raw_decode(text.split('const DATA = ', 1)[1])[0]
phases = {}
for tile in d['tiles']:
    for step, start, duration, activity in tile['samples']:
        phase, epoch, op, kernel, metadata, kind, horizon = d['steps'][step]
        if kind != 0:
            continue
        p = phases.setdefault((epoch, phase), dict(horizon=horizon, operation=d['strings'][op], starts=[], ends=[], activities=[]))
        p['starts'].append(start)
        p['ends'].append(start + duration)
        p['activities'].extend((a,b) for kind,a,b,*_ in d['activitySets'][activity] if kind != 2)
rows = []
for (epoch, phase), p in phases.items():
    cursor = 0
    gaps = []
    for start, end in sorted(p['activities']):
        if start > cursor:
            gaps.append((cursor, start))
        cursor = max(cursor, end)
    if cursor < p['horizon']:
        gaps.append((cursor, p['horizon']))
    first, last, end = min(p['starts']), max(p['starts']), max(p['ends'])
    rows.append(dict(epoch=epoch, phase=phase & 0x7fffffff, operation=p['operation'],
                     scheduled_cycles=p['horizon'], arrival_spread=last-first,
                     after_last_arrival=end-last, boundary_excess=end-last-p['horizon'],
                     maximum_global_gap=max((b-a for a,b in gaps), default=0),
                     maximum_interior_gap=max((b-a for a,b in gaps if a>0 and b<p['horizon']), default=0),
                     global_gaps=gaps))
print(json.dumps(sorted(rows, key=lambda r:r['boundary_excess'], reverse=True), indent=2))
