use std::sync::Arc;

use crate::err::TranslationErrors;
use crate::tree::typed_ast::context::StatementTranslationContext;

pub use crate::tree::options::{
    ExpressionTypeCheckOptions, ParseOptions, TranslateOptions, TypeCheckOptions,
};

pub mod clause;
pub mod command;
pub mod context;
pub mod display;
pub mod expression;
pub mod identifier;
pub mod node;
pub mod ops;
pub mod pattern;
pub mod pipeline;
pub mod query;

/// Trait for parsing strings into untyped AST nodes (Query, Pipeline, Expression, Identifier).
///
/// Provides three parsing methods with different error handling strategies.
/// See individual methods for when to use each.
///
/// Implementors only need to provide `parse_with_errors()`. The other two methods have
/// default implementations that delegate to it.
pub trait ParseWithErrors: Sized {
    fn parse(input: impl Into<String>) -> Self {
        Self::parse_with_errors(input).0
    }

    fn parse_result(input: impl Into<String>) -> Result<Self, TranslationErrors> {
        let (ast, errors) = Self::parse_with_errors(input);
        if errors.is_empty() {
            Ok(ast)
        } else {
            Err(errors)
        }
    }

    fn parse_with_errors(input: impl Into<String>) -> (Self, TranslationErrors);
}

/// Internal trait for types that can be parsed with a custom context.
pub trait ParseWithContext: Sized {
    fn parse_with_context(input: String, ctx: context::ParseContext) -> (Self, TranslationErrors);
}

/// Trait for AST types that can be type-checked with a translation context.
///
/// This trait abstracts the type-checking process for Query and Pipeline nodes,
/// allowing generic type-check functions to work for both types.
pub trait TypeCheck {
    type Output;

    fn type_check_with_context(
        ast: Arc<Self>,
        ctx: &mut StatementTranslationContext,
    ) -> Self::Output;
}
