use crate::{ContextWorker, ContextualizationError, Contextualizer, Escaper, Value};

#[derive(Debug, Default)]
/// A [`crate::Contextualizer`] you can use to opt out of the system entirely. As the name implies
/// this contextualizer does nothing. It only ever outputs the "text" default text type.
pub struct NoopContextualizer;

impl Contextualizer<NoopEscaper, NoopContextWorker> for NoopContextualizer {
    fn default_text_type(&self) -> String {
        "text".to_string()
    }

    fn contextualize(&self, text_ty: &str) -> Result<NoopContextWorker, ContextualizationError> {
        if text_ty != "text" {
            return Err(ContextualizationError::UnknownTextType(text_ty.to_string()));
        }

        Ok(NoopContextWorker)
    }
}

/// The [`crate::ContextWorker`] of the [`NoopContextualizer`]. Pushing static text does nothing
/// and it only ever outputs the default "text" text type.
pub struct NoopContextWorker;

impl ContextWorker<NoopEscaper> for NoopContextWorker {
    fn push_static(&mut self, _s: &str) -> Result<(), ContextualizationError> {
        Ok(())
    }

    fn dynamic(&mut self, input_ty: &str) -> Result<NoopEscaper, ContextualizationError> {
        if input_ty != "text" {
            return Err(ContextualizationError::UnknownTextType(
                input_ty.to_string(),
            ));
        }
        Ok(NoopEscaper)
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
/// The [`crate::Escaper`] of the [`NoopContextualizer`]. It always returns the [`crate::Value`]
/// unchanged.
pub struct NoopEscaper;

impl Escaper for NoopEscaper {
    fn escape<'a>(&self, inp: Value) -> Result<Value, String> {
        Ok(inp)
    }
}
