"""Offline pixel bbox validation. Python 3.10+; standard library only.

Contract: decoded, orientation-normalized raster; top-left origin, x right/y down.
Sizes are (width, height). Coordinates are pixels in that exact raster frame.
Integer crop output uses half-open edges [left,right) x [top,bottom).
This code does not run Florence-2 or read image metadata.
"""
from __future__ import annotations
import json
import math
import sys
from dataclasses import dataclass

MAX_DIMENSION = 1_000_000  # Arithmetic limit, not an image allocation permission.
MAX_RECORDS = 10_000

class InvalidBox(ValueError):
    pass


def finite_number(value, name):
    if type(value) not in (int, float):
        raise InvalidBox(f"{name}: expected a finite int or float, not bool")
    try:
        value = float(value)
    except (ValueError, OverflowError):
        raise InvalidBox(f"{name}: value is not representable") from None
    if not math.isfinite(value):
        raise InvalidBox(f"{name}: value must be finite")
    return value


def dimensions(size):
    if type(size) not in (list, tuple) or len(size) != 2:
        raise InvalidBox("size must be (width, height)")
    if any(type(v) is not int or not 0 < v <= MAX_DIMENSION for v in size):
        raise InvalidBox("width and height must be positive bounded integers")
    return tuple(size)


@dataclass(frozen=True)
class Frame:
    width: int
    height: int
    frame_id: str
    orientation_normalized: bool

    def __post_init__(self):
        dimensions((self.width, self.height))
        if type(self.frame_id) is not str or not self.frame_id or len(self.frame_id) > 128:
            raise InvalidBox("frame_id must be a nonempty string of at most 128 characters")
        if self.orientation_normalized is not True:
            raise InvalidBox("normalize EXIF orientation before assigning coordinates")

    @property
    def size(self):
        return (self.width, self.height)


def validate_box(box):
    if type(box) not in (list, tuple) or len(box) != 4:
        raise InvalidBox("bbox must contain four values: x0, y0, x1, y1")
    x0, y0, x1, y1 = [finite_number(v, "coordinate") for v in box]
    if not (x0 < x1 and y0 < y1):
        raise InvalidBox("bbox must satisfy x0 < x1 and y0 < y1")
    return (x0, y0, x1, y1)


def integer_crop(box, frame, *, box_frame_id, padding_px=0):
    """Validate, pad in destination pixels, floor/ceil, then clip.

    Reject a fully outside original box BEFORE padding. Padding is symmetric,
    nonnegative context expansion; it neither fills pixels nor rescues bad boxes.
    Frame identity is declared by the caller, not inferred from numeric ranges.
    """
    if not isinstance(frame, Frame):
        raise InvalidBox("frame must be a validated Frame")
    if box_frame_id != frame.frame_id or type(box_frame_id) is not str:
        raise InvalidBox("bbox and raster coordinate frames differ")
    x0, y0, x1, y1 = validate_box(box)
    pad = finite_number(padding_px, "padding_px")
    if pad < 0:
        raise InvalidBox("padding_px must be nonnegative")
    w, h = frame.size
    if x1 <= 0 or y1 <= 0 or x0 >= w or y0 >= h:
        raise InvalidBox("bbox has no positive-area overlap with the raster")
    expanded = tuple(finite_number(v, "padded coordinate") for v in
                     (x0-pad, y0-pad, x1+pad, y1+pad))
    left = max(0, min(w, math.floor(expanded[0])))
    top = max(0, min(h, math.floor(expanded[1])))
    right = max(0, min(w, math.ceil(expanded[2])))
    bottom = max(0, min(h, math.ceil(expanded[3])))
    if left >= right or top >= bottom:
        raise InvalidBox("integer crop has no pixels")
    return (left, top, right, bottom)


def uniform_resize_remap(box, source, target, *, mapping):
    """Only an explicit aligned full-raster uniform resize is supported.

    Same aspect ratio alone cannot prove alignment. The caller must establish no
    crop, letterbox, mirror, rotation, translation or content change occurred.
    The required mapping declaration records that assertion, not a verification.
    """
    if not isinstance(source, Frame) or not isinstance(target, Frame):
        raise InvalidBox("source and target must be validated Frames")
    if mapping != "aligned_full_raster_uniform_resize":
        raise InvalidBox("an explicit aligned full-raster resize is required")
    if source.width * target.height != source.height * target.width:
        raise InvalidBox("aspect ratios differ; crop or letterbox needs another transform")
    if source.frame_id == target.frame_id and source.size != target.size:
        raise InvalidBox("a resized raster needs a distinct frame_id")
    coords = validate_box(box)
    scale = target.width / source.width
    return validate_box([finite_number(v * scale, "remapped coordinate") for v in coords])


def florence_1000_bin_centers(bin_box, size):
    """Arithmetic illustration only, not the Florence parser or a model run.

    Mirrors the documented center formula for four valid location indices in
    the pinned Microsoft processor's 1000-bin setup. Python double arithmetic
    is not promised to be bit-identical to upstream tensor floating-point math.
    """
    w, h = dimensions(size)
    if type(bin_box) not in (list, tuple) or len(bin_box) != 4:
        raise InvalidBox("four bin indices required")
    if any(type(v) is not int or not 0 <= v < 1000 for v in bin_box):
        raise InvalidBox("bin indices must be integers in [0, 999], not bool")
    return tuple((v + 0.5) * (axis / 1000) for v, axis in zip(bin_box, (w, h, w, h)))


def process_od(payload, frame, *, box_frame_id, padding_px=0):
    """Validate an already post-processed <OD> object; report each bad box.

    Structural errors fail the whole request. Individual invalid bboxes retain
    their input index and error; labels are never filenames or filesystem paths.
    Other task types (OCR quads, polygons) are outside this adapter's scope.
    """
    if type(payload) is not dict or type(payload.get("<OD>")) is not dict:
        raise InvalidBox("expected a post-processed <OD> object")
    od = payload["<OD>"]
    boxes, labels = od.get("bboxes"), od.get("labels")
    if type(boxes) is not list or type(labels) is not list or len(boxes) != len(labels):
        raise InvalidBox("bboxes and labels must be equal-length lists")
    if len(boxes) > MAX_RECORDS:
        raise InvalidBox("too many records")
    if any(type(label) is not str for label in labels):
        raise InvalidBox("labels must be strings")
    results = []
    for index, (box, label) in enumerate(zip(boxes, labels)):
        result = {"index": index, "label": label}
        try:
            crop = integer_crop(box, frame, box_frame_id=box_frame_id, padding_px=padding_px)
            result.update(status="accepted", crop=list(crop), size=[crop[2]-crop[0], crop[3]-crop[1]])
        except InvalidBox as error:
            result.update(status="rejected", reason=str(error))
        results.append(result)
    return results


def main():
    """Read one bounded JSON request from stdin; write JSON to stdout only."""
    try:
        raw = sys.stdin.read(1_000_001)
        if len(raw) > 1_000_000:
            raise InvalidBox("JSON request exceeds 1,000,000 characters")
        def reject_constant(value):
            raise InvalidBox(f"non-standard JSON constant: {value}")
        request = json.loads(raw, parse_constant=reject_constant)
        if type(request) is not dict:
            raise InvalidBox("request must be an object")
        f = request["frame"]
        if type(f) is not dict:
            raise InvalidBox("frame must be an object")
        frame = Frame(f["width"], f["height"], f["frame_id"], f["orientation_normalized"])
        report = process_od(request["output"], frame,
                            box_frame_id=request["box_frame_id"],
                            padding_px=request.get("padding_px", 0))
        print(json.dumps({"results": report}, allow_nan=False, indent=2))
        return 0
    except (InvalidBox, KeyError, TypeError, json.JSONDecodeError, ValueError, RecursionError) as error:
        print(json.dumps({"error": str(error)}, allow_nan=False), file=sys.stderr)
        return 2


if __name__ == "__main__":
    raise SystemExit(main())
