use serde::Serialize;

const DEFAULT_AUDIO_WINDOW_MS: u32 = 5;
const DEFAULT_MAX_PAIR_GAP_S: f64 = 0.5;
const DEFAULT_PULSE_PERIOD_S: f64 = 1.0;
const DEFAULT_PULSE_WIDTH_S: f64 = 0.12;
const DEFAULT_MARKER_TICK_PERIOD: u32 = 5;

#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct SyncAnalysisReport {
    pub video_event_count: usize,
    pub audio_event_count: usize,
    pub paired_event_count: usize,
    pub first_skew_ms: f64,
    pub last_skew_ms: f64,
    pub mean_skew_ms: f64,
    pub median_skew_ms: f64,
    pub max_abs_skew_ms: f64,
    pub drift_ms: f64,
    pub skews_ms: Vec<f64>,
    pub video_onsets_s: Vec<f64>,
    pub audio_onsets_s: Vec<f64>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct SyncAnalysisOptions {
    pub audio_window_ms: u32,
    pub max_pair_gap_s: f64,
    pub pulse_period_s: f64,
    pub pulse_width_s: f64,
    pub marker_tick_period: u32,
}

impl Default for SyncAnalysisOptions {
    fn default() -> Self {
        Self {
            audio_window_ms: DEFAULT_AUDIO_WINDOW_MS,
            max_pair_gap_s: DEFAULT_MAX_PAIR_GAP_S,
            pulse_period_s: DEFAULT_PULSE_PERIOD_S,
            pulse_width_s: DEFAULT_PULSE_WIDTH_S,
            marker_tick_period: DEFAULT_MARKER_TICK_PERIOD,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::SyncAnalysisOptions;

    #[test]
    fn default_options_match_live_probe_expectations() {
        let options = SyncAnalysisOptions::default();
        assert_eq!(options.audio_window_ms, 5);
        assert!((options.max_pair_gap_s - 0.5).abs() < f64::EPSILON);
        assert!((options.pulse_period_s - 1.0).abs() < f64::EPSILON);
        assert!((options.pulse_width_s - 0.12).abs() < f64::EPSILON);
        assert_eq!(options.marker_tick_period, 5);
    }
}
