// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.searchlib.rankingexpression.rule;

import com.yahoo.searchlib.rankingexpression.evaluation.Value;

import java.util.List;
import java.util.function.BiFunction;

/**
 * A mathematical operator
 *
 * @author bratseth
 */
public enum ArithmeticOperator {

/*
struct Sub          : OperatorHelper<Sub>          { Sub()          : Helper("-", 101, LEFT)  {}};
struct Mul          : OperatorHelper<Mul>          { Mul()          : Helper("*", 102, LEFT)  {}};
struct Div          : OperatorHelper<Div>          { Div()          : Helper("/", 102, LEFT)  {}};
struct Mod          : OperatorHelper<Mod>          { Mod()          : Helper("%", 102, LEFT)  {}};
struct Pow          : OperatorHelper<Pow>          { Pow()          : Helper("^", 103, RIGHT) {}};
struct Equal        : OperatorHelper<Equal>        { Equal()        : Helper("==", 10, LEFT)  {}};
struct NotEqual     : OperatorHelper<NotEqual>     { NotEqual()     : Helper("!=", 10, LEFT)  {}};
struct Approx       : OperatorHelper<Approx>       { Approx()       : Helper("~=", 10, LEFT)  {}};
struct Less         : OperatorHelper<Less>         { Less()         : Helper("<",  10, LEFT)  {}};
struct LessEqual    : OperatorHelper<LessEqual>    { LessEqual()    : Helper("<=", 10, LEFT)  {}};
struct Greater      : OperatorHelper<Greater>      { Greater()      : Helper(">",  10, LEFT)  {}};
struct GreaterEqual : OperatorHelper<GreaterEqual> { GreaterEqual() : Helper(">=", 10, LEFT)  {}};
struct And          : OperatorHelper<And>          { And()          : Helper("&&",  2, LEFT)  {}};
struct Or           : OperatorHelper<Or>           { Or()           : Helper("||",  1, LEFT)  {}};
 */

    OR(0, "||", (x, y) -> x.or(y)),
    AND(1, "&&", (x, y) -> x.and(y)),
    PLUS(2, "+", (x, y) -> x.add(y)),
    MINUS(3, "-", (x, y) -> x.subtract(y)),
    MULTIPLY(4, "*", (x, y) -> x.multiply(y)),
    DIVIDE(5, "/", (x, y) -> x.divide(y)),
    MODULO(6, "%", (x, y) -> x.modulo(y)),
    POWER(7, "^", (x, y) -> x.power(y));

    /** A list of all the operators in this in order of decreasing precedence */
    public static final List<ArithmeticOperator> operatorsByPrecedence = List.of(POWER, MODULO, DIVIDE, MULTIPLY, MINUS, PLUS, AND, OR);

    private final int precedence;
    private final String image;
    private final BiFunction<Value, Value, Value> function;

    ArithmeticOperator(int precedence, String image, BiFunction<Value, Value, Value> function) {
        this.precedence = precedence;
        this.image = image;
        this.function = function;
    }

    /** Returns true if this operator has precedence over the given operator */
    public boolean hasPrecedenceOver(ArithmeticOperator op) {
        return precedence > op.precedence;
    }

    public final Value evaluate(Value x, Value y) {
        return function.apply(x, y);
    }

    @Override
    public String toString() {
        return image;
    }

}

@@ -211,24 +211,49 @@
 ion.Value;%0A%0A
+import java.util.Arrays;%0A
 import java.
@@ -1796,14 +1796,61 @@
     
+// In order from lowest to highest precedence%0A    
 OR(
-0, 
 %22%7C%7C%22
@@ -1879,19 +1879,16 @@
     AND(
-1, 
 %22&&%22, (x
@@ -1915,19 +1915,16 @@
    PLUS(
-2, 
 %22+%22, (x,
@@ -1951,19 +1951,16 @@
   MINUS(
-3, 
 %22-%22, (x,
@@ -1999,11 +1999,8 @@
 PLY(
-4, 
 %22*%22,
@@ -2041,11 +2041,8 @@
 IDE(
-5, 
 %22/%22,
@@ -2081,11 +2081,8 @@
 ULO(
-6, 
 %22%25%22,
@@ -2120,11 +2120,8 @@
 WER(
-7, 
 %22%5E%22,
@@ -2303,106 +2303,61 @@
 e = 
-List.of(POWER, MODULO, DIVIDE, MULTIPLY, MINUS, PLUS, AND, OR);%0A%0A    private final int precedence;
+Arrays.stream(ArithmeticOperator.values()).toList();%0A
 %0A   
@@ -2473,24 +2473,8 @@
 tor(
-int precedence, 
 Stri
@@ -2531,46 +2531,8 @@
 ) %7B%0A
-        this.precedence = precedence;%0A
     
@@ -2757,34 +2757,79 @@
 urn 
-precedence %3E op.precedence
+operatorsByPrecedence.indexOf(this) %3E operatorsByPrecedence.indexOf(op)
 ;%0A  

Use file order as precedence order