use std::iter::Peekable;

use crate::parser::{
    ast::operator::{BinaryOperator, LogicalOperator},
    ast::{between::Between, expression::Expression},
    expression::build_expression_with_priority,
    lexer::LexerItem,
    parser_error::ParserError,
    tokens::Token,
};

impl Between {
    pub(super) fn new(
        reference: Expression,
        lower_limit: Expression,
        upper_limit: Expression,
    ) -> Self {
        Self {
            reference: Box::new(reference),
            lower_limit: Box::new(lower_limit),
            upper_limit: Box::new(upper_limit),
        }
    }
}

pub(super) fn build_between(
    reference: Expression,
    lex: &mut Peekable<impl Iterator<Item = LexerItem>>,
) -> Result<Expression, ParserError> {
    lex.next();
    let lower_limit = build_expression_with_priority(lex, 0, |f| {
        f == Some(&Token::BinaryOperator(BinaryOperator::Logical(
            LogicalOperator::And,
        )))
    })?;
    lex.next();
    let upper_limit = build_expression_with_priority(lex, 10, |f| f.is_none())?;
    Ok(Expression::Between(Between::new(
        reference,
        lower_limit,
        upper_limit,
    )))
}
