//! Bounded recursive discovery for saved recording files.

use std::path::PathBuf;

pub const RECORDING_EXTENSION: &str = "recording";

pub fn find_recording_files(roots: &[PathBuf], max_depth: usize) -> Vec<PathBuf> {
    let mut found: Vec<PathBuf> = Vec::new();
    for root in roots {
        walk(root, max_depth, &mut found);
    }
    found.sort_by(|a, b| a.to_string_lossy().cmp(&b.to_string_lossy()));
    found.dedup();
    found
}

fn walk(dir: &std::path::Path, depth_left: usize, out: &mut Vec<PathBuf>) {
    let entries = match std::fs::read_dir(dir) {
        Ok(e) => e,
        Err(_) => return,
    };
    for entry in entries.flatten() {
        let path = entry.path();
        if path.is_dir() {
            if depth_left > 0 {
                walk(&path, depth_left - 1, out);
            }
        } else if path.extension().and_then(|e| e.to_str()) == Some(RECORDING_EXTENSION) {
            out.push(path);
        }
    }
}

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

    #[test]
    fn finds_recording_files_recursively_sorted_and_deduped() {
        let base = std::env::temp_dir().join(format!("rsstacker_filelist_{}", std::process::id()));
        let sub = base.join("sub");
        fs::create_dir_all(&sub).unwrap();
        fs::write(base.join("b.recording"), b"x").unwrap();
        fs::write(base.join("a.recording"), b"x").unwrap();
        fs::write(base.join("note.txt"), b"x").unwrap();
        fs::write(sub.join("c.recording"), b"x").unwrap();

        let found = find_recording_files(&[base.clone()], 3);
        let names: Vec<String> = found
            .iter()
            .map(|p| p.file_name().unwrap().to_string_lossy().into_owned())
            .collect();
        assert_eq!(names, vec!["a.recording", "b.recording", "c.recording"]);
        let twice = find_recording_files(&[base.clone(), base.clone()], 3);
        assert_eq!(twice.len(), 3);

        fs::remove_dir_all(&base).ok();
    }
}
