/*
 * 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 javax.el;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class LambdaExpression {

    private final List<String> formalParameters;
    private final ValueExpression expression;
    private final Map<String,Object> nestedArguments = new HashMap<>();
    private ELContext context = null;

    public LambdaExpression(List<String> formalParameters,
            ValueExpression expression) {
        this.formalParameters = formalParameters;
        this.expression = expression;

    }

    public void setELContext(ELContext context) {
        this.context = context;
    }

    @SuppressWarnings("null") // args[i] can't be null due to earlier checks
    public Object invoke(ELContext context, Object... args)
            throws ELException {

        Objects.requireNonNull(context);

        int formalParamCount = 0;
        if (formalParameters != null) {
            formalParamCount = formalParameters.size();
        }

        int argCount = 0;
        if (args != null) {
            argCount = args.length;
        }

        if (formalParamCount > argCount) {
            throw new ELException(Util.message(context,
                    "lambdaExpression.tooFewArgs",
                    Integer.valueOf(argCount),
                    Integer.valueOf(formalParamCount)));
        }

        // Build the argument map
        // Start with the arguments from any outer expressions so if there is
        // any overlap the local arguments have priority
        Map<String,Object> lambdaArguments = new HashMap<>();
        lambdaArguments.putAll(nestedArguments);
        for (int i = 0; i < formalParamCount; i++) {
            lambdaArguments.put(formalParameters.get(i), args[i]);
        }

        context.enterLambdaScope(lambdaArguments);

        try {
            Object result = expression.getValue(context);
            // Make arguments from this expression available to any nested
            // expression
            if (result instanceof LambdaExpression) {
                ((LambdaExpression) result).nestedArguments.putAll(
                        lambdaArguments);
            }
            return result;
        } finally {
            context.exitLambdaScope();
        }
    }

    public java.lang.Object invoke(Object... args) {
        return invoke (context, args);
    }
}
