#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct EyeSourceMode {
    pub width: u32,
    pub height: u32,
    pub fps: u32,
}

const GC311_H264_SOURCE_MODES: [EyeSourceMode; 2] = [
    EyeSourceMode {
        width: 1920,
        height: 1080,
        fps: 60,
    },
    EyeSourceMode {
        width: 1280,
        height: 720,
        fps: 60,
    },
];

pub fn native_eye_source_modes() -> &'static [EyeSourceMode] {
    &GC311_H264_SOURCE_MODES
}

pub fn default_eye_source_mode() -> EyeSourceMode {
    GC311_H264_SOURCE_MODES[0]
}

pub fn display_size_for_source_mode(mode: EyeSourceMode) -> (u32, u32) {
    match (mode.width, mode.height) {
        // GC311 exposes SD widescreen source modes with non-square pixels. Render them
        // into a square-pixel frame before the GTK preview consumes them.
        (720, 576) => (1024, 576),
        (720, 480) => (854, 480),
        _ => (mode.width, mode.height),
    }
}

pub fn eye_source_mode_for_request(requested_width: u32, requested_height: u32) -> EyeSourceMode {
    if requested_width == 0 || requested_height == 0 {
        return default_eye_source_mode();
    }

    native_eye_source_modes()
        .iter()
        .copied()
        .find(|mode| mode.width <= requested_width && mode.height <= requested_height)
        .unwrap_or_else(|| *native_eye_source_modes().last().expect("source mode list"))
}

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

    #[test]
    fn defaults_to_1080p60() {
        assert_eq!(
            default_eye_source_mode(),
            EyeSourceMode {
                width: 1920,
                height: 1080,
                fps: 60,
            }
        );
    }

    #[test]
    fn picks_the_highest_supported_mode_that_fits_the_request() {
        assert_eq!(
            eye_source_mode_for_request(1920, 1080),
            EyeSourceMode {
                width: 1920,
                height: 1080,
                fps: 60,
            }
        );
        assert_eq!(
            eye_source_mode_for_request(1600, 900),
            EyeSourceMode {
                width: 1280,
                height: 720,
                fps: 60,
            }
        );
        assert_eq!(
            eye_source_mode_for_request(960, 540),
            EyeSourceMode {
                width: 1280,
                height: 720,
                fps: 60,
            }
        );
    }

    #[test]
    fn reports_square_pixel_display_size_for_each_native_mode() {
        assert_eq!(
            display_size_for_source_mode(EyeSourceMode {
                width: 1920,
                height: 1080,
                fps: 60,
            }),
            (1920, 1080)
        );
        assert_eq!(
            display_size_for_source_mode(EyeSourceMode {
                width: 1280,
                height: 720,
                fps: 60,
            }),
            (1280, 720)
        );
    }
}
