/*
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde 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 net.hydromatic.linq4j.expressions;

import net.hydromatic.linq4j.function.*;

import java.lang.reflect.*;
import java.util.*;

/**
 * Represents a strongly typed lambda expression as a data structure in the form
 * of an expression tree. This class cannot be inherited.
 */
public final class FunctionExpression<F extends Function<?>>
    extends LambdaExpression {
  public final F function;
  public final BlockStatement body;
  public final List<ParameterExpression> parameterList;
  private F dynamicFunction;

  private FunctionExpression(Class<F> type, F function, BlockStatement body,
      List<ParameterExpression> parameterList) {
    super(ExpressionType.Lambda, type);
    assert type != null;
    assert function != null || body != null;
    this.function = function;
    this.body = body;
    this.parameterList = parameterList;
  }

  public FunctionExpression(F function) {
    this((Class) function.getClass(), function, null,
        Collections.<ParameterExpression>emptyList());
  }

  public FunctionExpression(Class<F> type, BlockStatement body,
      List<ParameterExpression> parameters) {
    this(type, null, body, parameters);
  }

  @Override
  public Expression accept(Visitor visitor) {
    BlockStatement body = this.body.accept(visitor);
    return visitor.visit(this, body, parameterList);
  }

  public Invokable compile() {
    return new Invokable() {
      public Object dynamicInvoke(Object... args) {
        final Evaluator evaluator = new Evaluator();
        for (int i = 0; i < args.length; i++) {
          evaluator.push(parameterList.get(i), args[i]);
        }
        return evaluator.evaluate(body);
      }
    };
  }

  public F getFunction() {
    if (function != null) {
      return function;
    }
    if (dynamicFunction == null) {
      final Invokable x = compile();

      //noinspection unchecked
      dynamicFunction = (F) Proxy.newProxyInstance(getClass().getClassLoader(),
          new Class[]{Types.toClass(type)},
          new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
              return x.dynamicInvoke(args);
            }
          });
    }
    return dynamicFunction;
  }

  @Override
  void accept(ExpressionWriter writer, int lprec, int rprec) {
    // "new Function1() {
    //    public Result apply(T1 p1, ...) {
    //        <body>
    //    }
    //    // bridge method
    //    public Object apply(Object p1, ...) {
    //        return apply((T1) p1, ...);
    //    }
    // }
    //
    // if any arguments are primitive there is an extra bridge method:
    //
    //  new Function1() {
    //    public double apply(double p1, int p2) {
    //      <body>
    //    }
    //    // box bridge method
    //    public Double apply(Double p1, Integer p2) {
    //      return apply(p1.doubleValue(), p2.intValue());
    //    }
    //    // bridge method
    //    public Object apply(Object p1, Object p2) {
    //      return apply((Double) p1, (Integer) p2);
    //    }
    List<String> params = new ArrayList<String>();
    List<String> bridgeParams = new ArrayList<String>();
    List<String> bridgeArgs = new ArrayList<String>();
    List<String> boxBridgeParams = new ArrayList<String>();
    List<String> boxBridgeArgs = new ArrayList<String>();
    for (ParameterExpression parameterExpression : parameterList) {
      final Type parameterType = parameterExpression.getType();
      final String parameterTypeName = Types.className(parameterType);
      final String parameterBoxTypeName = Types.boxClassName(parameterType);
      params.add(parameterTypeName + " " + parameterExpression.name);

      bridgeParams.add("Object " + parameterExpression.name);
      bridgeArgs.add("(" + parameterBoxTypeName + ") "
          + parameterExpression.name);

      boxBridgeParams.add(parameterBoxTypeName + " "
          + parameterExpression.name);
      boxBridgeArgs.add(parameterExpression.name
          + (Primitive.is(parameterType)
          ? "." + Primitive.of(parameterType).primitiveName + "Value()"
          : ""));
    }
    Type bridgeResultType = Functions.FUNCTION_RESULT_TYPES.get(this.type);
    if (bridgeResultType == null) {
      bridgeResultType = body.getType();
    }
    Type resultType2 = bridgeResultType;
    if (bridgeResultType == Object.class
        && !params.equals(bridgeParams)
        && !(body.getType() instanceof TypeVariable)) {
      resultType2 = body.getType();
    }
    writer.append("new ")
        .append(type)
        .append("()")
        .begin(" {\n")
        .append("public ")
        .append(Types.className(resultType2))
        .list(" apply(", ", ", ") ", params)
        .append(Blocks.toFunctionBlock(body));

    // Generate an intermediate bridge method if at least one parameter is
    // primitive.
    if (!boxBridgeParams.equals(params)) {
      writer
          .append("public ")
          .append(Types.boxClassName(bridgeResultType))
          .list(" apply(", ", ", ") ", boxBridgeParams)
          .begin("{\n")
          .list("return apply(\n", ",\n", ");\n", boxBridgeArgs)
          .end("}\n");
    }

    // Generate a bridge method. Argument types are looser (as if every
    // type parameter is set to 'Object').
    //
    // Skip the bridge method if there are no arguments. It would have the
    // same overload as the regular method.
    if (!bridgeParams.equals(params)) {
      writer
        .append("public ")
        .append(Types.boxClassName(bridgeResultType))
        .list(" apply(", ", ", ") ", bridgeParams)
        .begin("{\n")
        .list("return apply(\n", ",\n", ");\n", bridgeArgs)
        .end("}\n");
    }

    writer.end("}\n");
  }

  public interface Invokable {
    Object dynamicInvoke(Object... args);
  }
}

// End FunctionExpression.java
