"""Utility functions for signal processing."""

from ..constants import FPS
from ..models import NMSEvent


def build_idx_to_frame(successful_frames):
    """Build mapping from data index to video frame number."""
    return {i: int(successful_frames[i]) for i in range(len(successful_frames))}


def mask_to_regions(mask):
    """Convert a boolean mask to a list of (start, end) tuples. End is exclusive."""
    regions = []
    i = 0
    n = len(mask)
    while i < n:
        if mask[i]:
            start = i
            while i < n and mask[i]:
                i += 1
            regions.append((start, i))
        else:
            i += 1
    return regions


def merge_regions(regions, gap):
    """Merge regions separated by less than gap frames."""
    if not regions:
        return regions
    merged = [regions[0]]
    for start, end in regions[1:]:
        prev_start, prev_end = merged[-1]
        if start - prev_end <= gap:
            merged[-1] = (prev_start, end)
        else:
            merged.append((start, end))
    return merged


def merge_mouth_events(events, successful_frames=None, max_gap_frames=8):
    """Merge overlapping MOUTH-OPEN and LIP-ACTIVITY events into MOUTH-MOVEMENT."""
    if not events:
        return []

    intervals = sorted((e.start_frame, e.end_frame) for e in events)

    merged = [list(intervals[0])]
    for start, end in intervals[1:]:
        gap = start - merged[-1][1]
        if gap <= max_gap_frames:
            merged[-1][1] = max(merged[-1][1], end)
        else:
            merged.append([start, end])

    result = []
    for start, end in merged:
        duration_frames = end - start + 1
        best_conf = 0.0
        best_peak = start
        best_peak_val = 0.0
        for e in events:
            if e.start_frame <= end and e.end_frame >= start:
                if e.confidence > best_conf:
                    best_conf = e.confidence
                    best_peak = e.peak_frame
                    best_peak_val = e.peak_value

        result.append(
            NMSEvent(
                tier="MOUTH-MOVEMENT",
                start_frame=start,
                end_frame=end,
                peak_frame=best_peak,
                peak_value=best_peak_val,
                duration_ms=duration_frames * (1000.0 / FPS),
                confidence=best_conf,
                label="mouth movement",
            )
        )

    return result
