// License: see LICENSE file at root directory of `master` branch

use std::{
    io,
    path::{Path, PathBuf},
};

use dia_files::{
    filter::{
        self,
        NO_EXT,
        All, AllPaths, Case, IgnoredDirNames, IgnoredFileExts, NonSymlinkFiles, SomeDirNames, SomeFileExts, SomeFileNames, SymlinkFiles,
    },
};

#[test]
fn test_find_files() -> io::Result<()> {
    use dia_files::find_files;

    let dir = PathBuf::from(file!()).parent().unwrap().join("files");

    assert_eq!(find_files(&dir, true, AllPaths::new())?.count(), 6);

    assert_eq!(find_files(&dir, true, SomeDirNames::new(&["abc"], Case::Sensitive))?.count(), 6);
    assert_eq!(find_files(&dir, true, SomeDirNames::new(&["ABC"], Case::Sensitive))?.count(), 5);
    assert_eq!(find_files(&dir, true, SomeDirNames::new(&["aBC"], Case::Insensitive))?.count(), 6);

    assert_eq!(find_files(&dir, true, IgnoredDirNames::new(&["abc"], Case::Sensitive))?.count(), 5);
    assert_eq!(find_files(&dir, true, IgnoredDirNames::new(&["ABC"], Case::Sensitive))?.count(), 6);
    assert_eq!(find_files(&dir, true, IgnoredDirNames::new(&["AbC"], Case::Insensitive))?.count(), 5);

    assert_eq!(find_files(&dir, true, SomeFileExts::new(&["MD"], Case::Sensitive))?.count(), 0);
    assert_eq!(find_files(&dir, true, SomeFileExts::new(&["MD"], Case::Insensitive))?.count(), 3);
    assert_eq!(find_files(&dir, true, SomeFileExts::new(&[NO_EXT], Case::Insensitive))?.count(), 2);
    assert_eq!(find_files(&dir, true, SomeFileExts::new(&[NO_EXT], Case::Sensitive))?.count(), 2);

    assert_eq!(find_files(&dir, true, SomeFileNames::new(&["no-ext"], Case::Sensitive))?.count(), 1);
    assert_eq!(find_files(&dir, true, SomeFileNames::new(&["NO-EXT"], Case::Sensitive))?.count(), 0);
    assert_eq!(find_files(&dir, true, SomeFileNames::new(&["NO-EXT"], Case::Insensitive))?.count(), 1);

    assert_eq!(find_files(&dir, true, IgnoredFileExts::new(&["MD"], Case::Sensitive))?.count(), 6);
    assert_eq!(find_files(&dir, true, IgnoredFileExts::new(&["MD"], Case::Insensitive))?.count(), 3);
    assert_eq!(find_files(&dir, true, IgnoredFileExts::new(&["MD", NO_EXT], Case::Insensitive))?.count(), 1);
    assert_eq!(find_files(&dir, true, IgnoredFileExts::new(&["MD", NO_EXT], Case::Sensitive))?.count(), 4);

    assert_eq!(find_files(&dir, true, SymlinkFiles::new())?.count(), 2);
    assert_eq!(find_files(&dir, true, NonSymlinkFiles::new())?.count(), 4);

    let filter = All::new(vec![
        Box::new(SomeFileExts::new(&[NO_EXT], Case::Sensitive)),
        Box::new(SymlinkFiles::new()),
    ]);
    assert_eq!(find_files(&dir, true, filter)?.count(), 1);

    {
        struct Filter;
        impl filter::Filter for Filter {

            fn accept(&self, p: &Path) -> bool {
                if p.is_file() {
                    if let Some(Some(name)) = p.file_name().map(|n| n.to_str()) {
                        return ["b.md", "c.md"].contains(&name) == false;
                    }
                }
                true
            }

        }
        assert_eq!(dia_files::find_files(&dir, true, Filter)?.count(), 4);
        assert_eq!(dia_files::find_files(&dir, false, Filter)?.count(), 3);
    }


    Ok(())
}
