/*
 * 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.
 */
/* Generated By:JJTree: Do not edit this line. AstValue.java */
package org.apache.el.parser;

import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import jakarta.el.ELException;
import jakarta.el.ELResolver;
import jakarta.el.LambdaExpression;
import jakarta.el.MethodInfo;
import jakarta.el.MethodReference;
import jakarta.el.PropertyNotFoundException;
import jakarta.el.ValueReference;

import org.apache.el.lang.ELSupport;
import org.apache.el.lang.EvaluationContext;
import org.apache.el.stream.Optional;
import org.apache.el.util.MessageFactory;
import org.apache.el.util.ReflectionUtil;

public final class AstValue extends SimpleNode {

    private static final Object[] EMPTY_ARRAY = new Object[0];

    protected static class Target {
        protected Object base;

        protected Object property;
    }

    public AstValue(int id) {
        super(id);
    }

    @Override
    public Class<?> getType(EvaluationContext ctx) throws ELException {
        Target t = getTarget(ctx);
        ctx.setPropertyResolved(false);
        Class<?> result = ctx.getELResolver().getType(ctx, t.base, t.property);
        if (!ctx.isPropertyResolved()) {
            throw new PropertyNotFoundException(MessageFactory.get("error.resolver.unhandled", t.base, t.property));
        }
        return result;
    }

    private Target getTarget(EvaluationContext ctx) throws ELException {
        // evaluate expr-a to value-a
        Object base = this.children[0].getValue(ctx);

        // if our base is null (we know there are more properties to evaluate)
        if (base == null) {
            throw new PropertyNotFoundException(
                    MessageFactory.get("error.unreachable.base", this.children[0].getImage()));
        }

        // set up our start/end
        Object property = null;
        int propCount = this.jjtGetNumChildren();

        int i = 1;
        // Evaluate any properties or methods before our target
        ELResolver resolver = ctx.getELResolver();
        while (i < propCount) {
            if (i + 2 < propCount && this.children[i + 1] instanceof AstMethodParameters) {
                // Method call not at end of expression
                base = resolver.invoke(ctx, base, this.children[i].getValue(ctx), null,
                        ((AstMethodParameters) this.children[i + 1]).getParameters(ctx));
                i += 2;
            } else if (i + 2 == propCount && this.children[i + 1] instanceof AstMethodParameters) {
                // Method call at end of expression
                ctx.setPropertyResolved(false);
                property = this.children[i].getValue(ctx);
                if (property == null) {
                    throw new PropertyNotFoundException(
                            MessageFactory.get("error.unreachable.property", this.children[i].getImage()));
                }
                i += 2;
            } else if (i + 1 < propCount) {
                // Object with property not at end of expression
                property = this.children[i].getValue(ctx);
                ctx.setPropertyResolved(false);
                base = resolver.getValue(ctx, base, property);
                i++;
            } else {
                // Object with property at end of expression
                ctx.setPropertyResolved(false);
                property = this.children[i].getValue(ctx);
                if (property == null) {
                    throw new PropertyNotFoundException(
                            MessageFactory.get("error.unreachable.property", this.children[i].getImage()));
                }
                i++;
            }
            if (base == null) {
                throw new PropertyNotFoundException(
                        MessageFactory.get("error.unreachable.property", this.children[propCount - 1].getImage()));
            }
        }

        Target t = new Target();
        t.base = base;
        t.property = property;
        return t;
    }

    @Override
    public Object getValue(EvaluationContext ctx) throws ELException {
        Object base = this.children[0].getValue(ctx);
        int propCount = this.jjtGetNumChildren();
        int i = 1;
        Object suffix = null;
        ELResolver resolver = ctx.getELResolver();
        while (base != null && i < propCount) {
            suffix = this.children[i].getValue(ctx);
            if (i + 1 < propCount && (this.children[i + 1] instanceof AstMethodParameters mps)) {
                if (base instanceof Optional && "orElseGet".equals(suffix) && mps.jjtGetNumChildren() == 1) {
                    Node paramFoOptional = mps.jjtGetChild(0);
                    if (!(paramFoOptional instanceof AstLambdaExpression ||
                            paramFoOptional instanceof LambdaExpression)) {
                        throw new ELException(MessageFactory.get("stream.optional.paramNotLambda", suffix));
                    }
                }
                // This is a method
                Object[] paramValues = mps.getParameters(ctx);
                base = resolver.invoke(ctx, base, suffix, getTypesFromValues(paramValues), paramValues);
                i += 2;
            } else {
                // This is a property
                if (suffix == null) {
                    return null;
                }

                ctx.setPropertyResolved(false);
                base = resolver.getValue(ctx, base, suffix);
                i++;
            }
        }
        if (!ctx.isPropertyResolved()) {
            throw new PropertyNotFoundException(MessageFactory.get("error.resolver.unhandled", base, suffix));
        }
        return base;
    }

    @Override
    public boolean isReadOnly(EvaluationContext ctx) throws ELException {
        Target t = getTarget(ctx);
        ctx.setPropertyResolved(false);
        boolean result = ctx.getELResolver().isReadOnly(ctx, t.base, t.property);
        if (!ctx.isPropertyResolved()) {
            throw new PropertyNotFoundException(MessageFactory.get("error.resolver.unhandled", t.base, t.property));
        }
        return result;
    }

    @Override
    public void setValue(EvaluationContext ctx, Object value) throws ELException {
        Target t = getTarget(ctx);
        ctx.setPropertyResolved(false);
        ELResolver resolver = ctx.getELResolver();

        // coerce to the expected type
        Class<?> targetClass = resolver.getType(ctx, t.base, t.property);
        resolver.setValue(ctx, t.base, t.property, ELSupport.coerceToType(ctx, value, targetClass));
        if (!ctx.isPropertyResolved()) {
            throw new PropertyNotFoundException(MessageFactory.get("error.resolver.unhandled", t.base, t.property));
        }
    }

    @Override
    // Interface el.parser.Node uses raw types (and is auto-generated)
    public MethodInfo getMethodInfo(EvaluationContext ctx, @SuppressWarnings("rawtypes") Class[] paramTypes)
            throws ELException {
        Target t = getTarget(ctx);
        Class<?>[] types;
        if (isParametersProvided()) {
            Object[] values = ((AstMethodParameters) this.jjtGetChild(this.jjtGetNumChildren() - 1)).getParameters(ctx);
            types = getTypesFromValues(values);
        } else {
            types = paramTypes;
        }
        Method m = ReflectionUtil.getMethod(ctx, t.base, t.property, types, null);
        return new MethodInfo(m.getName(), m.getReturnType(), m.getParameterTypes());
    }

    @Override
    // Interface el.parser.Node uses a raw type (and is auto-generated)
    public Object invoke(EvaluationContext ctx, @SuppressWarnings("rawtypes") Class[] paramTypes, Object[] paramValues)
            throws ELException {

        Target t = getTarget(ctx);
        Method m;
        Object[] values;
        Class<?>[] types;
        if (isParametersProvided()) {
            values = ((AstMethodParameters) this.jjtGetChild(this.jjtGetNumChildren() - 1)).getParameters(ctx);
            types = getTypesFromValues(values);
        } else {
            values = paramValues;
            types = paramTypes;
        }
        m = ReflectionUtil.getMethod(ctx, t.base, t.property, types, values);

        // Handle varArgs and any coercion required
        values = convertArgs(ctx, values, m);

        Object result;
        try {
            result = m.invoke(t.base, values);
        } catch (IllegalAccessException | IllegalArgumentException e) {
            throw new ELException(e);
        } catch (InvocationTargetException ite) {
            Throwable cause = ite.getCause();
            if (cause instanceof VirtualMachineError) {
                throw (VirtualMachineError) cause;
            }
            throw new ELException(cause);
        }
        return result;
    }

    @Override
    public MethodReference getMethodReference(EvaluationContext ctx) {
        Target t = getTarget(ctx);
        Method m;
        Object[] values = null;
        Class<?>[] types = null;
        if (isParametersProvided()) {
            values = ((AstMethodParameters) this.jjtGetChild(this.jjtGetNumChildren() - 1)).getParameters(ctx);
            types = getTypesFromValues(values);
        }
        m = ReflectionUtil.getMethod(ctx, t.base, t.property, types, values);

        // Handle varArgs and any coercion required
        values = convertArgs(ctx, values, m);

        return new MethodReference(t.base, getMethodInfo(ctx, types), m.getAnnotations(), values);
    }

    private Object[] convertArgs(EvaluationContext ctx, Object[] src, Method m) {
        Class<?>[] types = m.getParameterTypes();
        if (types.length == 0) {
            // Treated as if parameters have been provided so src is ignored
            return EMPTY_ARRAY;
        }

        int paramCount = types.length;

        if (m.isVarArgs() && paramCount > 1 && (src == null || paramCount > src.length) ||
                !m.isVarArgs() && (src == null || src.length != paramCount)) {
            String srcCount = null;
            if (src != null) {
                srcCount = Integer.toString(src.length);
            }
            String msg;
            if (m.isVarArgs()) {
                msg = MessageFactory.get("error.invoke.tooFewParams", m.getName(), srcCount,
                        Integer.toString(paramCount));
            } else {
                msg = MessageFactory.get("error.invoke.wrongParams", m.getName(), srcCount,
                        Integer.toString(paramCount));
            }
            throw new IllegalArgumentException(msg);
        }

        if (src == null) {
            // Must be a varargs method with a single parameter.
            // Use a new array every time since the called code could modify the
            // contents of the array
            return new Object[1];
        }

        Object[] dest = new Object[paramCount];

        for (int i = 0; i < paramCount - 1; i++) {
            dest[i] = ELSupport.coerceToType(ctx, src[i], types[i]);
        }

        if (m.isVarArgs()) {
            Class<?> varArgType = m.getParameterTypes()[paramCount - 1].getComponentType();
            if (varArgType.equals(Integer.class)) {
                Integer[] varArgs = new Integer[src.length - (paramCount - 1)];
                for (int i = 0; i < src.length - (paramCount - 1); i++) {
                    varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], Integer.class);
                }
                dest[paramCount - 1] = varArgs;
            } else if (varArgType.equals(Byte.class)) {
                Byte[] varArgs = new Byte[src.length - (paramCount - 1)];
                for (int i = 0; i < src.length - (paramCount - 1); i++) {
                    varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], Byte.class);
                }
                dest[paramCount - 1] = varArgs;
            } else if (varArgType.equals(Boolean.class)) {
                Boolean[] varArgs = new Boolean[src.length - (paramCount - 1)];
                for (int i = 0; i < src.length - (paramCount - 1); i++) {
                    varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], Boolean.class);
                }
                dest[paramCount - 1] = varArgs;
            } else if (varArgType.equals(Short.class)) {
                Short[] varArgs = new Short[src.length - (paramCount - 1)];
                for (int i = 0; i < src.length - (paramCount - 1); i++) {
                    varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], Short.class);
                }
                dest[paramCount - 1] = varArgs;
            } else if (varArgType.equals(Long.class)) {
                Long[] varArgs = new Long[src.length - (paramCount - 1)];
                for (int i = 0; i < src.length - (paramCount - 1); i++) {
                    varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], Long.class);
                }
                dest[paramCount - 1] = varArgs;
            } else if (varArgType.equals(Double.class)) {
                Double[] varArgs = new Double[src.length - (paramCount - 1)];
                for (int i = 0; i < src.length - (paramCount - 1); i++) {
                    varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], Double.class);
                }
                dest[paramCount - 1] = varArgs;
            } else if (varArgType.equals(Float.class)) {
                Float[] varArgs = new Float[src.length - (paramCount - 1)];
                for (int i = 0; i < src.length - (paramCount - 1); i++) {
                    varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], Float.class);
                }
                dest[paramCount - 1] = varArgs;
            } else if (varArgType.equals(Character.class)) {
                Character[] varArgs = new Character[src.length - (paramCount - 1)];
                for (int i = 0; i < src.length - (paramCount - 1); i++) {
                    varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], Character.class);
                }
                dest[paramCount - 1] = varArgs;
            } else if (varArgType.equals(int.class)) {
                int[] varArgs = new int[src.length - (paramCount - 1)];
                for (int i = 0; i < src.length - (paramCount - 1); i++) {
                    varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], int.class).intValue();
                }
                dest[paramCount - 1] = varArgs;
            } else if (varArgType.equals(byte.class)) {
                byte[] varArgs = new byte[src.length - (paramCount - 1)];
                for (int i = 0; i < src.length - (paramCount - 1); i++) {
                    varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], byte.class).byteValue();
                }
                dest[paramCount - 1] = varArgs;
            } else if (varArgType.equals(boolean.class)) {
                boolean[] varArgs = new boolean[src.length - (paramCount - 1)];
                for (int i = 0; i < src.length - (paramCount - 1); i++) {
                    varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], boolean.class).booleanValue();
                }
                dest[paramCount - 1] = varArgs;
            } else if (varArgType.equals(short.class)) {
                short[] varArgs = new short[src.length - (paramCount - 1)];
                for (int i = 0; i < src.length - (paramCount - 1); i++) {
                    varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], short.class).shortValue();
                }
                dest[paramCount - 1] = varArgs;
            } else if (varArgType.equals(long.class)) {
                long[] varArgs = new long[src.length - (paramCount - 1)];
                for (int i = 0; i < src.length - (paramCount - 1); i++) {
                    varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], long.class).longValue();
                }
                dest[paramCount - 1] = varArgs;
            } else if (varArgType.equals(double.class)) {
                double[] varArgs = new double[src.length - (paramCount - 1)];
                for (int i = 0; i < src.length - (paramCount - 1); i++) {
                    varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], double.class).doubleValue();
                }
                dest[paramCount - 1] = varArgs;
            } else if (varArgType.equals(float.class)) {
                float[] varArgs = new float[src.length - (paramCount - 1)];
                for (int i = 0; i < src.length - (paramCount - 1); i++) {
                    varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], float.class).floatValue();
                }
                dest[paramCount - 1] = varArgs;
            } else if (varArgType.equals(char.class)) {
                char[] varArgs = new char[src.length - (paramCount - 1)];
                for (int i = 0; i < src.length - (paramCount - 1); i++) {
                    varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], char.class).charValue();
                }
                dest[paramCount - 1] = varArgs;
            } else {
                Object[] varArgs = (Object[]) Array.newInstance(varArgType, src.length - (paramCount - 1));
                for (int i = 0; i < src.length - (paramCount - 1); i++) {
                    varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], varArgType);
                }
                dest[paramCount - 1] = varArgs;
            }
        } else {
            dest[paramCount - 1] = ELSupport.coerceToType(ctx, src[paramCount - 1], types[paramCount - 1]);
        }

        return dest;
    }

    private Class<?>[] getTypesFromValues(Object[] values) {
        if (values == null) {
            return null;
        }

        Class<?>[] result = new Class<?>[values.length];
        for (int i = 0; i < values.length; i++) {
            if (values[i] == null) {
                result[i] = null;
            } else {
                result[i] = values[i].getClass();
            }
        }
        return result;
    }


    /**
     * @since EL 2.2
     */
    @Override
    public ValueReference getValueReference(EvaluationContext ctx) {
        // Check this is a reference to a base and a property
        if (this.children.length > 2 && this.jjtGetChild(2) instanceof AstMethodParameters) {
            // This is a method call
            return null;
        }
        Target t = getTarget(ctx);
        return new ValueReference(t.base, t.property);
    }


    /**
     * @since EL 2.2
     */
    @Override
    public boolean isParametersProvided() {
        // Assumption is that method parameters, if present, will be the last
        // child
        int len = children.length;
        if (len > 2) {
            return this.jjtGetChild(len - 1) instanceof AstMethodParameters;
        }
        return false;
    }
}
