//! 屏幕捕获模块

use anyhow::Result;
use scrap::{Capturer, Display};
use std::io::ErrorKind::WouldBlock;
use std::time::Duration;

/// 屏幕捕获器
pub struct ScreenCapturer {
    capturer: Capturer,
    width: u32,
    height: u32,
}

impl ScreenCapturer {
    /// 创建新的屏幕捕获器
    pub fn new(display_index: usize) -> Result<Self> {
        let displays = Display::all()?;
        if display_index >= displays.len() {
            anyhow::bail!("Invalid display index: {}", display_index);
        }

        let display = displays.into_iter().nth(display_index).unwrap();
        let width = display.width() as u32;
        let height = display.height() as u32;

        let capturer = Capturer::new(display)?;

        Ok(Self {
            capturer,
            width,
            height,
        })
    }

    /// 获取屏幕宽度
    pub fn width(&self) -> u32 {
        self.width
    }

    /// 获取屏幕高度
    pub fn height(&self) -> u32 {
        self.height
    }

    /// 捕获一帧
    pub fn capture_frame(&mut self) -> Result<Option<Vec<u8>>> {
        match self.capturer.frame() {
            Ok(frame) => {
                // scrap 返回的是 BGRA 格式
                let data = frame.to_vec();
                Ok(Some(data))
            }
            Err(ref e) if e.kind() == WouldBlock => {
                // 没有新帧，稍后重试
                Ok(None)
            }
            Err(e) => Err(e.into()),
        }
    }

    /// 捕获并转换为 RGBA
    pub fn capture_rgba(&mut self) -> Result<Option<Vec<u8>>> {
        if let Some(bgra) = self.capture_frame()? {
            let mut rgba = bgra;
            // BGRA -> RGBA
            for chunk in rgba.chunks_exact_mut(4) {
                chunk.swap(0, 2);
            }
            Ok(Some(rgba))
        } else {
            Ok(None)
        }
    }
}

/// 获取所有显示器信息
pub fn get_displays() -> Result<Vec<DisplayInfo>> {
    let displays = Display::all()?;
    Ok(displays
        .into_iter()
        .enumerate()
        .map(|(i, d)| DisplayInfo {
            index: i,
            width: d.width() as u32,
            height: d.height() as u32,
            is_primary: i == 0, // scrap 没有提供 is_primary，默认第一个为主显示器
        })
        .collect())
}

/// 显示器信息
#[derive(Debug, Clone)]
pub struct DisplayInfo {
    pub index: usize,
    pub width: u32,
    pub height: u32,
    pub is_primary: bool,
}

/// 帧率控制器
pub struct FrameRateLimiter {
    target_interval: Duration,
    last_frame: std::time::Instant,
}

impl FrameRateLimiter {
    pub fn new(fps: u32) -> Self {
        Self {
            target_interval: Duration::from_secs_f64(1.0 / fps as f64),
            last_frame: std::time::Instant::now(),
        }
    }

    /// 等待到下一帧时间
    pub fn wait(&mut self) {
        let elapsed = self.last_frame.elapsed();
        if elapsed < self.target_interval {
            std::thread::sleep(self.target_interval - elapsed);
        }
        self.last_frame = std::time::Instant::now();
    }

    /// 更新目标帧率
    pub fn set_fps(&mut self, fps: u32) {
        self.target_interval = Duration::from_secs_f64(1.0 / fps as f64);
    }
}

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

    #[test]
    fn test_get_displays() {
        let displays = get_displays().unwrap();
        assert!(!displays.is_empty());
        println!("Found {} displays", displays.len());
        for d in &displays {
            println!(
                "Display {}: {}x{} (primary: {})",
                d.index, d.width, d.height, d.is_primary
            );
        }
    }
}
