use crate::check::{Check, Finding};
use koala_core::invariant::Context;

pub struct Registry {
    checks: Vec<Box<dyn Check>>,
}

impl Registry {
    pub fn empty() -> Self {
        Self { checks: Vec::new() }
    }

    pub fn from_checks(checks: Vec<Box<dyn Check>>) -> Self {
        Self { checks }
    }

    pub fn builtin() -> Self {
        use crate::checks::{
            adr_dormancy, adr_no_delete, arch_claims, feature_acceptance, feature_adr_refs,
            feature_status_impl, template_placeholder, tier1_integrity,
        };
        Self::from_checks(vec![
            Box::new(feature_acceptance::FeatureAcceptanceTestRef),
            Box::new(feature_adr_refs::FeatureAdrRefs),
            Box::new(feature_status_impl::FeatureStatusHasImpl),
            Box::new(adr_dormancy::AdrDormancy),
            Box::new(adr_no_delete::AdrNoDelete),
            Box::new(tier1_integrity::Tier1Integrity),
            Box::new(arch_claims::ArchClaims),
            Box::new(template_placeholder::TemplatePlaceholder),
        ])
    }

    pub fn checks(&self) -> impl Iterator<Item = &dyn Check> {
        self.checks.iter().map(|c| c.as_ref())
    }

    pub fn len(&self) -> usize {
        self.checks.len()
    }

    pub fn is_empty(&self) -> bool {
        self.checks.is_empty()
    }

    pub fn run_all(&self, ctx: &Context) -> Vec<Finding> {
        let mut out = Vec::new();
        for c in &self.checks {
            out.extend(c.run(ctx));
        }
        out
    }
}
