/*
 * 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.JexlContext;
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 org.apache.commons.jexl3.parser.ParserVisitor;


import org.apache.commons.logging.Log;

/**
 * The helper base of an interpreter of JEXL syntax.
 * @since 3.0
 */
public abstract class InterpreterBase extends ParserVisitor {
    /** The JEXL engine. */
    protected final Engine jexl;
    /** The logger. */
    protected final Log logger;
    /** The uberspect. */
    protected final JexlUberspect uberspect;
    /** The arithmetic handler. */
    protected final JexlArithmetic arithmetic;
    /** The context to store/retrieve variables. */
    protected final JexlContext context;
    /** Cancellation support. */
    protected volatile boolean cancelled = false;
    /** Empty parameters for method matching. */
    protected static final Object[] EMPTY_PARAMS = new Object[0];

    /**
     * Creates an interpreter base.
     * @param engine   the engine creating this interpreter
     * @param aContext the context to evaluate expression
     */
    protected InterpreterBase(Engine engine, JexlContext aContext) {
        this.jexl = engine;
        this.logger = jexl.logger;
        this.uberspect = jexl.uberspect;
        this.context = aContext != null ? aContext : Engine.EMPTY_CONTEXT;
        if (this.context instanceof JexlEngine.Options) {
            JexlEngine.Options opts = (JexlEngine.Options) context;
            this.arithmetic = jexl.arithmetic.options(opts);
            if (!arithmetic.getClass().equals(jexl.arithmetic.getClass())) {
                logger.error("expected arithmetic to be " + jexl.arithmetic.getClass().getSimpleName()
                              + ", got " + arithmetic.getClass().getSimpleName()
                );
            }
        } else {
            this.arithmetic = jexl.arithmetic;
        }
    }

    /** Java7 AutoCloseable interface defined?. */
    protected static final Class<?> AUTOCLOSEABLE;
    static {
        Class<?> c;
        try {
            c = Class.forName("java.lang.AutoCloseable");
        } catch (ClassNotFoundException xclass) {
            c = null;
        }
        AUTOCLOSEABLE = c;
    }

    /**
     * Attempt to call close() if supported.
     * <p>This is used when dealing with auto-closeable (duck-like) objects
     * @param closeable the object we'd like to close
     */
    protected void closeIfSupported(Object closeable) {
        if (closeable != null) {
            //if (AUTOCLOSEABLE == null || AUTOCLOSEABLE.isAssignableFrom(closeable.getClass())) {
            JexlMethod mclose = uberspect.getMethod(closeable, "close", EMPTY_PARAMS);
            if (mclose != null) {
                try {
                    mclose.invoke(closeable, EMPTY_PARAMS);
                } catch (Exception xignore) {
                    logger.warn(xignore);
                }
            }
            //}
        }
    }

    /**
     * Whether this interpreter is currently evaluating with a strict engine flag.
     * @return true if strict engine, false otherwise
     */
    protected boolean isStrictEngine() {
        if (this.context instanceof JexlEngine.Options) {
            JexlEngine.Options opts = (JexlEngine.Options) context;
            Boolean strict = opts.isStrict();
            if (strict != null) {
                return strict.booleanValue();
            }
        }
        return jexl.isStrict();
    }

    /**
     * Whether this interpreter is currently evaluating with a silent mode.
     * @return true if silent, false otherwise
     */
    protected boolean isSilent() {
        if (this.context instanceof JexlEngine.Options) {
            JexlEngine.Options opts = (JexlEngine.Options) context;
            Boolean silent = opts.isSilent();
            if (silent != null) {
                return silent.booleanValue();
            }
        }
        return jexl.isSilent();
    }

    /** @return true if interrupt throws a JexlException.Cancel. */
    protected boolean isCancellable() {
        if (this.context instanceof JexlEngine.Options) {
            JexlEngine.Options opts = (JexlEngine.Options) context;
            Boolean ocancellable = opts.isCancellable();
            if (ocancellable != null) {
                return ocancellable.booleanValue();
            }
        }
        return jexl.cancellable;
    }

    /**
     * Finds the node causing a NPE for diadic operators.
     * @param xrt   the RuntimeException
     * @param node  the parent node
     * @param left  the left argument
     * @param right the right argument
     * @return the left, right or parent node
     */
    protected JexlNode findNullOperand(RuntimeException xrt, JexlNode node, Object left, Object right) {
        if (xrt instanceof JexlArithmetic.NullOperand) {
            if (left == null) {
                return node.jjtGetChild(0);
            }
            if (right == null) {
                return node.jjtGetChild(1);
            }
        }
        return node;
    }

    /**
     * Triggered when a variable can not be resolved.
     * @param node  the node where the error originated from
     * @param var   the variable name
     * @param undef whether the variable is undefined or null
     * @return throws JexlException if strict and not silent, null otherwise
     */
    protected Object unsolvableVariable(JexlNode node, String var, boolean undef) {
        if (isStrictEngine()) {
            if (isSilent()) {
                logger.warn(JexlException.variableError(node, var, undef));
            } else if (undef || arithmetic.isStrict()){
                throw new JexlException.Variable(node, var, undef);
            }
        } else if (logger.isDebugEnabled()) {
            logger.debug(JexlException.variableError(node, var, undef));
        }
        return null;
    }

    /**
     * Triggered when a method can not be resolved.
     * @param node   the node where the error originated from
     * @param method the method name
     * @return throws JexlException if strict and not silent, null otherwise
     */
    protected Object unsolvableMethod(JexlNode node, String method) {
        if (isStrictEngine()) {
            if (isSilent()) {
                logger.warn(JexlException.methodError(node, method));
            } else {
                throw new JexlException.Method(node, method);
            }
        } else if (logger.isDebugEnabled()) {
            logger.debug(JexlException.methodError(node, method));
        }
        return null;
    }

    /**
     * Triggered when a property can not be resolved.
     * @param node  the node where the error originated from
     * @param var   the property name
     * @param cause the cause if any
     * @return throws JexlException if strict and not silent, null otherwise
     */
    protected Object unsolvableProperty(JexlNode node, String var, Throwable cause) {
        if (isStrictEngine()) {
            if (isSilent()) {
                logger.warn(JexlException.propertyError(node, var), cause);
            } else {
                throw new JexlException.Property(node, var, cause);
            }
        } else if (logger.isDebugEnabled()) {
            logger.debug(JexlException.propertyError(node, var), cause);
        }
        return null;
    }

    /**
     * Triggered when an operator fails.
     * @param node     the node where the error originated from
     * @param operator the method name
     * @param cause    the cause of error (if any)
     * @return throws JexlException if strict and not silent, null otherwise
     */
    protected Object operatorError(JexlNode node, JexlOperator operator, Throwable cause) {
        if (isStrictEngine()) {
            if (isSilent()) {
                logger.warn(JexlException.operatorError(node, operator.getOperatorSymbol()), cause);
            } else {
                throw new JexlException.Operator(node, operator.getOperatorSymbol(), cause);
            }
        } else if (logger.isDebugEnabled()) {
            logger.debug(JexlException.operatorError(node, operator.getOperatorSymbol()), cause);
        }
        return null;
    }

    /**
     * Triggered when method, function or constructor invocation fails.
     * @param xjexl the JexlException wrapping the original error
     * @return throws a JexlException if strict and not silent, null otherwise
     */
    protected Object invocationFailed(JexlException xjexl) {
        if (xjexl instanceof JexlException.Return
            || xjexl instanceof JexlException.Cancel) {
            throw xjexl;
        }
        if (isStrictEngine())  {
            if (isSilent()) {
                logger.warn(xjexl.getMessage(), xjexl.getCause());
            } else {
                throw xjexl;
            }
        } else if (logger.isDebugEnabled()) {
            logger.debug(xjexl);
        }
        return null;
    }

    /**
     * Wraps an exception thrown by an invocation.
     * @param node       the node triggering the exception
     * @param methodName the method/function name
     * @param xany       the cause
     * @return a JexlException
     */
    protected JexlException exceptionOnInvocation(JexlNode node, String methodName, Exception xany) {
        Throwable cause = xany.getCause();
        if (cause instanceof JexlException) {
            return (JexlException) cause;
        }
        if (cause instanceof InterruptedException) {
            cancelled = true;
            return new JexlException.Cancel(node);
        }
        return new JexlException(node, methodName, xany);
    }

    /**
     * Triggered when an annotation processing fails.
     * @param node     the node where the error originated from
     * @param annotation the annotation name
     * @param cause    the cause of error (if any)
     * @return throws a JexlException if strict and not silent, null otherwise
     */
    protected Object annotationError(JexlNode node, String annotation, Throwable cause) {
        if (isStrictEngine()) {
            if (isSilent()) {
                logger.warn(JexlException.annotationError(node, annotation), cause);
            } else {
                throw new JexlException.Annotation(node, annotation, cause);
            }
        } else if (logger.isDebugEnabled()) {
            logger.debug(JexlException.annotationError(node, annotation), cause);
        }
        return null;
    }

    /**
     * Cancels this evaluation, setting the cancel flag that will result in a JexlException.Cancel to be thrown.
     * @return false if already cancelled, true otherwise
     */
    protected synchronized boolean  cancel() {
        if (cancelled) {
            return false;
        } else {
            cancelled = true;
            return true;
        }
    }

    /**
     * Checks whether this interpreter execution was canceled due to thread interruption.
     * @return true if canceled, false otherwise
     */
    protected synchronized boolean isCancelled() {
        if (!cancelled) {
            cancelled = Thread.currentThread().isInterrupted();
        }
        return cancelled;
    }
}
