use super::PredicateEvaluator;
use crate::evaluator::{FileContext, MatchResult};
use crate::parser::PredicateKey;
use anyhow::Result;

pub(super) struct ExtEvaluator;
impl PredicateEvaluator for ExtEvaluator {
    fn evaluate(
        &self,
        context: &mut FileContext,
        _key: &PredicateKey,
        value: &str,
    ) -> Result<MatchResult> {
        let file_ext = context
            .path
            .extension()
            .and_then(|s| s.to_str())
            .unwrap_or("");
        Ok(MatchResult::Boolean(file_ext.eq_ignore_ascii_case(value)))
    }
}

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

    #[test]
    fn test_ext_evaluator() {
        let mut context_rs = FileContext::new(PathBuf::from("main.rs"), PathBuf::from("/"));
        let mut context_toml = FileContext::new(PathBuf::from("Cargo.TOML"), PathBuf::from("/"));
        let mut context_no_ext = FileContext::new(PathBuf::from("README"), PathBuf::from("/"));
        let mut context_dotfile = FileContext::new(PathBuf::from(".bashrc"), PathBuf::from("/"));

        let evaluator = ExtEvaluator;
        assert!(evaluator
            .evaluate(&mut context_rs, &PredicateKey::Ext, "rs")
            .unwrap()
            .is_match());
        assert!(!evaluator
            .evaluate(&mut context_rs, &PredicateKey::Ext, "toml")
            .unwrap()
            .is_match());
        assert!(
            evaluator
                .evaluate(&mut context_toml, &PredicateKey::Ext, "toml")
                .unwrap()
                .is_match(),
            "Should be case-insensitive"
        );
        assert!(!evaluator
            .evaluate(&mut context_no_ext, &PredicateKey::Ext, "rs")
            .unwrap()
            .is_match());
        assert!(
            !evaluator
                .evaluate(&mut context_dotfile, &PredicateKey::Ext, "bashrc")
                .unwrap()
                .is_match(),
            "Dotfiles should have no extension"
        );
    }
}
