use crate::prelude::*;

use crate::terms::Term;
use crate::triples::TripleRef;

use super::{AndFilter, ObjectFilter, OrFilter, PredicateFilter, SubjectFilter, TripleFilter};

// FIXME maybe use something that can resolve filters by names,…
pub struct BasicFilters;

impl BasicFilters {
    pub fn s(subject: &Term) -> SubjectFilter<'_> {
        SubjectFilter::new(subject)
    }

    pub fn p(predicate: &Term) -> PredicateFilter<'_> {
        PredicateFilter::new(predicate)
    }

    pub fn o(object: &Term) -> ObjectFilter<'_> {
        ObjectFilter::new(object)
    }

    pub fn sp<'a, 'b>(
        subject: &'a Term,
        predicate: &'b Term,
    ) -> AndFilter<SubjectFilter<'a>, PredicateFilter<'b>> {
        AndFilter::new(SubjectFilter::new(subject), PredicateFilter::new(predicate))
    }

    pub fn so<'a, 'b>(
        subject: &'a Term,
        object: &'b Term,
    ) -> AndFilter<SubjectFilter<'a>, ObjectFilter<'b>> {
        AndFilter::new(SubjectFilter::new(subject), ObjectFilter::new(object))
    }

    pub fn po<'a, 'b>(
        predicate: &'a Term,
        object: &'b Term,
    ) -> AndFilter<PredicateFilter<'a>, ObjectFilter<'b>> {
        AndFilter::new(PredicateFilter::new(predicate), ObjectFilter::new(object))
    }

    pub fn spo<'a, 'b, 'c>(
        subject: &'a Term,
        predicate: &'b Term,
        object: &'c Term,
    ) -> AndFilter<AndFilter<SubjectFilter<'a>, PredicateFilter<'b>>, ObjectFilter<'c>> {
        AndFilter::new(
            AndFilter::new(SubjectFilter::new(subject), PredicateFilter::new(predicate)),
            ObjectFilter::new(object),
        )
    }

    pub fn describes(value: &Term) -> OrFilter<SubjectFilter<'_>, ObjectFilter<'_>> {
        OrFilter::new(SubjectFilter::new(value), ObjectFilter::new(value))
    }
    // FIXME add type; needs rdf.resolve() method (?)
}
