//! DataFusion translations for arithmetic operators.

use datafusion::logical_expr::{BinaryExpr, Expr as DFExpr, Operator as DFOperator};

use hamelin_lib::func::defs::{
    NumericDivide, NumericMinus, NumericModulo, NumericMultiply, NumericPlus,
};

use super::DataFusionTranslationRegistry;

pub fn register(registry: &mut DataFusionTranslationRegistry) {
    // left + right -> left + right
    registry.register::<NumericPlus>(|mut params| {
        let left = params.take()?.expr;
        let right = params.take()?.expr;
        Ok(DFExpr::BinaryExpr(BinaryExpr::new(
            Box::new(left),
            DFOperator::Plus,
            Box::new(right),
        )))
    });

    // left - right -> left - right
    registry.register::<NumericMinus>(|mut params| {
        let left = params.take()?.expr;
        let right = params.take()?.expr;
        Ok(DFExpr::BinaryExpr(BinaryExpr::new(
            Box::new(left),
            DFOperator::Minus,
            Box::new(right),
        )))
    });

    // left * right -> left * right
    registry.register::<NumericMultiply>(|mut params| {
        let left = params.take()?.expr;
        let right = params.take()?.expr;
        Ok(DFExpr::BinaryExpr(BinaryExpr::new(
            Box::new(left),
            DFOperator::Multiply,
            Box::new(right),
        )))
    });

    // left / right -> left / right
    registry.register::<NumericDivide>(|mut params| {
        let left = params.take()?.expr;
        let right = params.take()?.expr;
        Ok(DFExpr::BinaryExpr(BinaryExpr::new(
            Box::new(left),
            DFOperator::Divide,
            Box::new(right),
        )))
    });

    // left % right -> left % right
    registry.register::<NumericModulo>(|mut params| {
        let left = params.take()?.expr;
        let right = params.take()?.expr;
        Ok(DFExpr::BinaryExpr(BinaryExpr::new(
            Box::new(left),
            DFOperator::Modulo,
            Box::new(right),
        )))
    });
}
