/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.jexl3.internal;

import org.apache.commons.jexl3.JexlArithmetic;
import org.apache.commons.jexl3.JexlEngine;
import org.apache.commons.jexl3.JexlException;
import org.apache.commons.jexl3.JexlOperator;
import org.apache.commons.jexl3.introspection.JexlMethod;
import org.apache.commons.jexl3.introspection.JexlUberspect;
import org.apache.commons.jexl3.parser.JexlNode;

import java.util.Iterator;
/**
 * Helper class to deal with operator overloading and specifics.
 * @since 3.0
 */
public class Operators {
    /** The owner. */
    protected final Interpreter interpreter;
    /** The overloaded arithmetic operators. */
    protected final JexlArithmetic.Uberspect operators;

    /**
     * Constructor.
     * @param owner the owning interpreter
     */
    protected Operators(Interpreter owner) {
        final JexlArithmetic arithmetic = owner.arithmetic;
        final JexlUberspect uberspect = owner.uberspect;
        this.interpreter = owner;
        this.operators = uberspect.getArithmetic(arithmetic);
    }

    /**
     * Checks whether a method returns a boolean or a Boolean.
     * @param vm the JexlMethod (may be null)
     * @return true of false
     */
    private boolean returnsBoolean(JexlMethod vm) {
        if (vm !=null) {
            Class<?> rc = vm.getReturnType();
            return Boolean.TYPE.equals(rc) || Boolean.class.equals(rc);
        }
        return false;
    }

    /**
     * Attempts to call an operator.
     * <p>
     * This takes care of finding and caching the operator method when appropriate
     * @param node     the syntactic node
     * @param operator the operator
     * @param args     the arguments
     * @return the result of the operator evaluation or TRY_FAILED
     */
    protected Object tryOverload(JexlNode node, JexlOperator operator, Object... args) {
        if (operators != null && operators.overloads(operator)) {
            final JexlArithmetic arithmetic = interpreter.arithmetic;
            final boolean cache = interpreter.cache;
            if (cache) {
                Object cached = node.jjtGetValue();
                if (cached instanceof JexlMethod) {
                    JexlMethod me = (JexlMethod) cached;
                    Object eval = me.tryInvoke(operator.getMethodName(), arithmetic, args);
                    if (!me.tryFailed(eval)) {
                        return eval;
                    }
                }
            }
            try {
                JexlMethod vm = operators.getOperator(operator, args);
                if (vm != null) {
                    Object result = vm.invoke(arithmetic, args);
                    if (cache) {
                        node.jjtSetValue(vm);
                    }
                    return result;
                }
            } catch (Exception xany) {
                interpreter.operatorError(node, operator, xany);
            }
        }
        return JexlEngine.TRY_FAILED;
    }

    /**
     * Attempts to call an overloaded forEach operator.
     * <p>
     * This takes care of finding and caching the operator method when appropriate
     * @param node     the syntactic node
     * @param arg      the argument
     * @return the result of the operator evaluation or TRY_FAILED
     */
    protected Object tryForeachOverload(JexlNode node, Object arg) {
        if (operators != null && operators.overloads(JexlOperator.FOR_EACH)) {
            final JexlArithmetic arithmetic = interpreter.arithmetic;
            final boolean cache = interpreter.cache;
            if (cache) {
                Object cached = node.jjtGetValue();
                if (cached instanceof JexlMethod) {
                    JexlMethod me = (JexlMethod) cached;
                    Object eval = me.tryInvoke(JexlOperator.FOR_EACH.getMethodName(), arithmetic, arg);
                    if (!me.tryFailed(eval)) {
                        return eval;
                    }
                }
            }
            try {
                JexlMethod vm = operators.getOperator(JexlOperator.FOR_EACH, arg);
                if (vm != null && Iterator.class.isAssignableFrom(vm.getReturnType())) {
                    Object result = vm.invoke(arithmetic, arg);
                    if (cache) {
                        node.jjtSetValue(vm);
                    }
                    return result;
                }
            } catch (Exception xany) {
                interpreter.operatorError(node, JexlOperator.FOR_EACH, xany);
            }
        }
        return JexlEngine.TRY_FAILED;
    }

    /**
     * Evaluates an assign operator.
     * <p>
     * This takes care of finding and caching the operator method when appropriate.
     * If an overloads returns Operator.ASSIGN, it means the side-effect is complete.
     * Otherwise, a += b &lt;=&gt; a = a + b
     * </p>
     * @param node     the syntactic node
     * @param operator the operator
     * @param args     the arguments, the first one being the target of assignment
     * @return the result of the operator evaluation
     */
    protected Object tryAssignOverload(JexlNode node, JexlOperator operator, Object...args) {
        final JexlArithmetic arithmetic = interpreter.arithmetic;
        if (args.length != operator.getArity()) {
            return JexlEngine.TRY_FAILED;
        }
        // try to call overload on side effect
        Object result = tryOverload(node, operator, args);
        if (result != JexlEngine.TRY_FAILED) {
            return result;
        }
        // call base operator
        JexlOperator base = operator.getBaseOperator();
        if (base == null) {
            throw new IllegalArgumentException("must be called with a side-effect operator");
        }
        if (operators != null && operators.overloads(base)) {
            // in case there is an overload
            try {
                JexlMethod vm = operators.getOperator(base, args);
                if (vm != null) {
                    result = vm.invoke(arithmetic, args);
                    if (result != JexlEngine.TRY_FAILED) {
                        return result;
                    }
                }
            } catch (Exception xany) {
                interpreter.operatorError(node, base, xany);
            }
        }
        // base eval
        switch (operator) {
            case SELF_ADD:
                return arithmetic.add(args[0], args[1]);
            case SELF_SUBTRACT:
                return arithmetic.subtract(args[0], args[1]);
            case SELF_MULTIPLY:
                return arithmetic.multiply(args[0], args[1]);
            case SELF_DIVIDE:
                return arithmetic.divide(args[0], args[1]);
            case SELF_MOD:
                return arithmetic.mod(args[0], args[1]);
            case SELF_AND:
                return arithmetic.and(args[0], args[1]);
            case SELF_OR:
                return arithmetic.or(args[0], args[1]);
            case SELF_XOR:
                return arithmetic.xor(args[0], args[1]);
            default:
                throw new JexlException.Operator(node, operator.getOperatorSymbol(), null);
        }
    }

    /**
     * The 'startsWith' operator implementation.
     * @param node     the node
     * @param operator the calling operator, $= or $!
     * @param left     the left operand
     * @param right    the right operand
     * @return true if left starts with right, false otherwise
     */
    protected boolean startsWith(JexlNode node, String operator, Object left, Object right) {
        final JexlArithmetic arithmetic = interpreter.arithmetic;
        final JexlUberspect uberspect = interpreter.uberspect;
        try {
            // try operator overload
            Object result = tryOverload(node, JexlOperator.STARTSWITH, left, right);
            if (result instanceof Boolean) {
                return (Boolean) result;
            }
            // use arithmetic / pattern matching ?
            Boolean matched = arithmetic.startsWith(left, right);
            if (matched != null) {
                return matched;
            }
            // try a startsWith method (duck type)
            try {
                Object[] argv = {right};
                JexlMethod vm = uberspect.getMethod(left, "startsWith", argv);
                if (returnsBoolean(vm)) {
                    return (Boolean) vm.invoke(left, argv);
                } else if (arithmetic.narrowArguments(argv)) {
                    vm = uberspect.getMethod(left, "startsWith", argv);
                    if (returnsBoolean(vm)) {
                        return (Boolean) vm.invoke(left, argv);
                    }
                }
            } catch (Exception e) {
                throw new JexlException(node, operator + " error", e);
            }
            // defaults to equal
            return arithmetic.equals(left, right) ? Boolean.TRUE : Boolean.FALSE;
        } catch (ArithmeticException xrt) {
            throw new JexlException(node, operator + " error", xrt);
        }
    }

    /**
     * The 'endsWith' operator implementation.
     * @param node     the node
     * @param operator the calling operator, ^= or ^!
     * @param left     the left operand
     * @param right    the right operand
     * @return true if left ends with right, false otherwise
     */
    protected boolean endsWith(JexlNode node, String operator, Object left, Object right) {
        final JexlArithmetic arithmetic = interpreter.arithmetic;
        final JexlUberspect uberspect = interpreter.uberspect;
        try {
            // try operator overload
            Object result = tryOverload(node, JexlOperator.ENDSWITH, left, right);
            if (result instanceof Boolean) {
                return (Boolean) result;
            }
            // use arithmetic / pattern matching ?
            Boolean matched = arithmetic.endsWith(left, right);
            if (matched != null) {
                return matched;
            }
            // try a endsWith method (duck type)
            try {
                Object[] argv = {right};
                JexlMethod vm = uberspect.getMethod(left, "endsWith", argv);
                if (returnsBoolean(vm)) {
                    return (Boolean) vm.invoke(left, argv);
                } else if (arithmetic.narrowArguments(argv)) {
                    vm = uberspect.getMethod(left, "endsWith", argv);
                    if (returnsBoolean(vm)) {
                        return (Boolean) vm.invoke(left, argv);
                    }
                }
            } catch (Exception e) {
                throw new JexlException(node, operator + " error", e);
            }
            // defaults to equal
            return arithmetic.equals(left, right) ? Boolean.TRUE : Boolean.FALSE;
        } catch (ArithmeticException xrt) {
            throw new JexlException(node, operator + " error", xrt);
        }
    }

    /**
     * The 'match'/'in' operator implementation.
     * <p>
     * Note that 'x in y' or 'x matches y' means 'y contains x' ;
     * the JEXL operator arguments order syntax is the reverse of this method call.
     * </p>
     * @param node  the node
     * @param op    the calling operator, =~ or !~
     * @param right the left operand
     * @param left  the right operand
     * @return true if left matches right, false otherwise
     */
    protected boolean contains(JexlNode node, String op, Object left, Object right) {
        final JexlArithmetic arithmetic = interpreter.arithmetic;
        final JexlUberspect uberspect = interpreter.uberspect;
        try {
            // try operator overload
            Object result = tryOverload(node, JexlOperator.CONTAINS, left, right);
            if (result instanceof Boolean) {
                return (Boolean) result;
            }
            // use arithmetic / pattern matching ?
            Boolean matched = arithmetic.contains(left, right);
            if (matched != null) {
                return matched;
            }
            // try a contains method (duck type set)
            try {
                Object[] argv = {right};
                JexlMethod vm = uberspect.getMethod(left, "contains", argv);
                if (returnsBoolean(vm)) {
                    return (Boolean) vm.invoke(left, argv);
                } else if (arithmetic.narrowArguments(argv)) {
                    vm = uberspect.getMethod(left, "contains", argv);
                    if (returnsBoolean(vm)) {
                        return (Boolean) vm.invoke(left, argv);
                    }
                }
            } catch (Exception e) {
                throw new JexlException(node, op + " error", e);
            }
            // defaults to equal
            return arithmetic.equals(left, right);
        } catch (ArithmeticException xrt) {
            throw new JexlException(node, op + " error", xrt);
        }
    }

    /**
     * Check for emptyness of various types: Collection, Array, Map, String, and anything that has a boolean isEmpty()
     * method.
     * <p>Note that the result may not be a boolean.
     *
     * @param node   the node holding the object
     * @param object the object to check the emptyness of
     * @return the evaluation result
     */
    protected Object empty(JexlNode node, Object object) {
        if (object == null) {
            return Boolean.TRUE;
        }
        final JexlArithmetic arithmetic = interpreter.arithmetic;
        final JexlUberspect uberspect = interpreter.uberspect;
        Object result = Operators.this.tryOverload(node, JexlOperator.EMPTY, object);
        if (result != JexlEngine.TRY_FAILED) {
            return result;
        }
        result = arithmetic.isEmpty(object);
        if (result == null) {
            result = false;
            // check if there is an isEmpty method on the object that returns a
            // boolean and if so, just use it
            JexlMethod vm = uberspect.getMethod(object, "isEmpty", Interpreter.EMPTY_PARAMS);
            if (returnsBoolean(vm)) {
                try {
                    result = (Boolean) vm.invoke(object, Interpreter.EMPTY_PARAMS);
                } catch (Exception xany) {
                    interpreter.operatorError(node, JexlOperator.EMPTY, xany);
                }
            }
        }
        return result;
    }

    /**
     * Calculate the <code>size</code> of various types:
     * Collection, Array, Map, String, and anything that has a int size() method.
     * <p>Note that the result may not be an integer.
     *
     * @param node   the node that gave the value to size
     * @param object the object to get the size of.
     * @return the evaluation result
     */
    protected Object size(JexlNode node, Object object) {
        if (object == null) {
            return 0;
        }
        final JexlArithmetic arithmetic = interpreter.arithmetic;
        final JexlUberspect uberspect = interpreter.uberspect;
        Object result = Operators.this.tryOverload(node, JexlOperator.SIZE, object);
        if (result != JexlEngine.TRY_FAILED) {
            return result;
        }
        result = arithmetic.size(object);
        if (result == null) {
            // check if there is a size method on the object that returns an
            // integer and if so, just use it
            JexlMethod vm = uberspect.getMethod(object, "size", Interpreter.EMPTY_PARAMS);
            if (vm != null && (Integer.TYPE.equals(vm.getReturnType()) || Integer.class.equals(vm.getReturnType()))) {
                try {
                    result = (Integer) vm.invoke(object, Interpreter.EMPTY_PARAMS);
                } catch (Exception xany) {
                    interpreter.operatorError(node, JexlOperator.SIZE, xany);
                }
            }
        }
        return result;
    }
}
