"""Deterministic nearest-PTS observation selection with bounded display/context."""
import bisect
import math


def make_plan(pts, bounds):
    if not pts or any(not math.isfinite(p) for p in pts) or any(b <= a for a,b in zip(pts,pts[1:])):
        raise ValueError('Missing, invalid or non-monotonic source PTS')
    times = [p-pts[0] for p in pts]
    grid = [i/10 for i in range(math.floor(times[-1]*10+1e-8)+1)]
    indices = []
    for target in grid:
        right = bisect.bisect_left(times,target)
        candidates = [j for j in (right-1,right) if 0 <= j < len(times)]
        indices.append(min(candidates,key=lambda j:(abs(times[j]-target),j)))
    if len(set(indices)) != len(indices):
        raise ValueError('10FPS would duplicate source frames; no upsampling allowed')
    lo,hi = bounds if bounds is not None else (1,len(times))
    if not 1 <= lo <= hi <= len(times): raise ValueError('Display range outside source file')
    display = [i for i,k in enumerate(indices) if lo <= k+1 <= hi]
    if not display: raise ValueError('No observations in requested range')
    stop = min(len(indices),max(display)+8)
    return dict(source_frames=len(times),source_pts_origin=pts[0],display_bounds=[lo,hi],
                full_grid_count=len(grid),display_samples=display,target_seconds=grid[:stop],
                source_frame_indices=[i+1 for i in indices[:stop]],
                relative_seconds=[times[i] for i in indices[:stop]],
                max_sampling_error_seconds=max(abs(times[j]-t) for j,t in zip(indices[:stop],grid[:stop])),
                tracking_start='file start',input_context='prefix through last display observation +7, bounded by source',
                synthetic_frames=False)
