// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed 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 com.google.devtools.build.lib.syntax;

import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.events.Location.LineAndColumn;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.ProfilerTask;
import com.google.devtools.build.lib.syntax.compiler.ByteCodeUtils;
import com.google.devtools.build.lib.syntax.compiler.DebugInfo;
import com.google.devtools.build.lib.syntax.compiler.LoopLabels;
import com.google.devtools.build.lib.syntax.compiler.ReflectionUtils;
import com.google.devtools.build.lib.syntax.compiler.VariableScope;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.asm.ClassVisitorWrapper;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.modifier.MethodManifestation;
import net.bytebuddy.description.modifier.Ownership;
import net.bytebuddy.description.modifier.TypeManifestation;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType.Unloaded;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
import net.bytebuddy.implementation.bytecode.member.MethodReturn;
import net.bytebuddy.matcher.ElementMatchers;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.util.Textifier;
import org.objectweb.asm.util.TraceClassVisitor;

/**
 * The actual function registered in the environment. This function is defined in the
 * parsed code using {@link FunctionDefStatement}.
 */
public class UserDefinedFunction extends BaseFunction {

  private final ImmutableList<Statement> statements;

  // we close over the globals at the time of definition
  private final Environment.Frame definitionGlobals;

  private Optional<Method> method;
  // TODO(bazel-team) make this configurable once the compiler is stable
  public static boolean debugCompiler = false;
  public static boolean debugCompilerPrintByteCode = false;
  private static File debugFolder;
  public static boolean enableCompiler = false;

  protected UserDefinedFunction(
      Identifier function,
      FunctionSignature.WithValues<Object, SkylarkType> signature,
      ImmutableList<Statement> statements,
      Environment.Frame definitionGlobals)
      throws EvalException {
    super(function.getName(), signature, function.getLocation());
    this.statements = statements;
    this.definitionGlobals = definitionGlobals;
    method = enableCompiler ? buildCompiledFunction() : Optional.<Method>absent();
  }

  public FunctionSignature.WithValues<Object, SkylarkType> getFunctionSignature() {
    return signature;
  }

  ImmutableList<Statement> getStatements() {
    return statements;
  }

  @Override
  public Object call(Object[] arguments, FuncallExpression ast, Environment env)
      throws EvalException, InterruptedException {
    if (!env.mutability().isMutable()) {
      throw new EvalException(getLocation(), "Trying to call in frozen environment");
    }
    if (env.getStackTrace().contains(this)) {
      throw new EvalException(getLocation(),
          String.format("Recursion was detected when calling '%s' from '%s'",
              getName(), Iterables.getLast(env.getStackTrace()).getName()));
    }

    if (enableCompiler && method.isPresent()) {
      Object returnValue = callCompiledFunction(arguments, ast, env);
      if (returnValue != null) {
        return returnValue;
      }
    }

    Profiler.instance().startTask(ProfilerTask.SKYLARK_USER_FN, getName());
    try {
      env.enterScope(this, ast, definitionGlobals);
      ImmutableList<String> names = signature.getSignature().getNames();

      // Registering the functions's arguments as variables in the local Environment
      int i = 0;
      for (String name : names) {
        env.update(name, arguments[i++]);
      }

      try {
        for (Statement stmt : statements) {
          if (stmt instanceof ReturnStatement) {
            // Performance optimization.
            // Executing the statement would throw an exception, which is slow.
            return ((ReturnStatement) stmt).getReturnExpression().eval(env);
          } else {
            stmt.exec(env);
          }
        }
      } catch (ReturnStatement.ReturnException e) {
        return e.getValue();
      }
      return Runtime.NONE;
    } finally {
      Profiler.instance().completeTask(ProfilerTask.SKYLARK_USER_FN);
      env.exitScope();
    }
  }

  private Object callCompiledFunction(Object[] arguments, FuncallExpression ast, Environment env) {
    compilerDebug("Calling compiled function " + getLocationPathAndLine() + " " + getName());
    try {
      Profiler.instance().startTask(ProfilerTask.SKYLARK_USER_COMPILED_FN,
          getLocationPathAndLine() + "#" + getName());
      env.enterScope(this, ast, definitionGlobals);

      return method
          .get()
          .invoke(null, ImmutableList.builder().add(arguments).add(env).build().toArray());

    } catch (IllegalAccessException e) {
      // this should never happen
      throw new RuntimeException(
          "Compiler created code that could not be accessed reflectively.", e);
    } catch (InvocationTargetException e) {
      compilerDebug("Error running compiled version", e.getCause());
      return null;
    } finally {
      Profiler.instance().completeTask(ProfilerTask.SKYLARK_USER_COMPILED_FN);
      env.exitScope();
    }
  }

  /**
   * Generates a subclass of {@link CompiledFunction} with a static method "call" and static
   * methods for getting information from a {@link DebugInfo} instance.
   *
   * <p>The "call" method contains the compiled version of this function's AST.
   */
  private Optional<Method> buildCompiledFunction() throws EvalException {
    // replace the / character in the path so we have file system compatible class names
    // the java specification mentions that $ should be used in generated code
    // see http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.8
    String path =
        location.getPath() != null ? location.getPath().getPathString().replace('/', '$') : "";
    String compiledFunctionClassName =
        CompiledFunction.class.getCanonicalName() + path + "$" + getName();
    compilerDebug("Compiling " + getLocationPathAndLine() + " " + getName());
    try {
      int publicStatic = Visibility.PUBLIC.getMask() | Ownership.STATIC.getMask();
      TypeDescription.Latent latentCompiledFunctionClass =
          new TypeDescription.Latent(
              compiledFunctionClassName,
              publicStatic | TypeManifestation.FINAL.getMask(),
              new TypeDescription.ForLoadedType(CompiledFunction.class),
              Collections.<TypeDescription>emptyList());
      MethodDescription getAstNode =
          new MethodDescription.Latent(
              latentCompiledFunctionClass,
              new MethodDescription.Token(
                  "getAstNode",
                  publicStatic | MethodManifestation.FINAL.getMask(),
                  new TypeDescription.ForLoadedType(ASTNode.class),
                  Arrays.asList(new TypeDescription.ForLoadedType(int.class))));
      MethodDescription getLocation =
          new MethodDescription.Latent(
              latentCompiledFunctionClass,
              new MethodDescription.Token(
                  "getLocation",
                  publicStatic | MethodManifestation.FINAL.getMask(),
                  new TypeDescription.ForLoadedType(Location.class),
                  Arrays.asList(new TypeDescription.ForLoadedType(int.class))));

      DebugInfo debugInfo = new DebugInfo(getAstNode, getLocation);
      FunctionSignature sig = signature.getSignature();
      VariableScope scope = VariableScope.function(sig.getNames());
      Implementation compiledImplementation = compileBody(scope, debugInfo);

      List<Class<?>> parameterTypes = sig.getShape().toClasses();
      parameterTypes.add(Environment.class);
      Unloaded<CompiledFunction> unloadedImplementation =
          new ByteBuddy()
              .withClassVisitor(new StackMapFrameClassVisitor(debugCompilerPrintByteCode))
              .subclass(CompiledFunction.class)
              .name(compiledFunctionClassName)
              .defineMethod(
                  "call",
                  Object.class,
                  parameterTypes,
                  Visibility.PUBLIC,
                  Ownership.STATIC,
                  MethodManifestation.FINAL)
              .intercept(compiledImplementation)
              .defineMethod(getAstNode)
              // TODO(bazel-team) unify the two delegate fields into one, probably needs a custom
              // ImplementationDelegate that adds it only once? or just create the static field
              // itself with the correct value and create getAstNode & getLocation with a custom
              // implementation using it
              .intercept(
                  MethodDelegation.to(debugInfo, DebugInfo.class, "getAstNodeDelegate")
                      .filter(ElementMatchers.named("getAstNode")))
              .defineMethod(getLocation)
              .intercept(
                  MethodDelegation.to(debugInfo, DebugInfo.class, "getLocationDelegate")
                      .filter(ElementMatchers.named("getLocation")))
              .make();
      saveByteCode(unloadedImplementation);
      Class<? extends CompiledFunction> functionClass =
          unloadedImplementation
              .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
              .getLoaded();

      return Optional.of(
          ReflectionUtils.getMethod(
                  functionClass,
                  "call",
                  parameterTypes.toArray(new Class<?>[parameterTypes.size()]))
              .getLoadedMethod());
    } catch (EvalException e) {
      // don't capture EvalExceptions
      throw e;
    } catch (Throwable e) {
      compilerDebug("Error while compiling", e);
      // TODO(bazel-team) don't capture all throwables? couldn't compile this, log somewhere?
    }
    return Optional.absent();
  }

  /**
   * Saves byte code to a temporary directory prefixed with "skylarkbytecode" in the system
   * default temporary directory.
   */
  private void saveByteCode(Unloaded<CompiledFunction> unloadedImplementation) {
    if (debugCompiler) {
      try {
        if (debugFolder == null) {
          debugFolder = Files.createTempDirectory("skylarkbytecode").toFile();
        }
        unloadedImplementation.saveIn(debugFolder);
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }
  }

  /**
   * Builds a byte code implementation of the AST.
   */
  private Implementation compileBody(VariableScope scope, DebugInfo debugInfo)
      throws EvalException {
    List<ByteCodeAppender> code = new ArrayList<>(statements.size());
    code.add(null); // reserve space for later addition of the local variable initializer

    for (Statement statement : statements) {
      code.add(statement.compile(scope, LoopLabels.ABSENT, debugInfo));
    }
    // add a return None if there are no statements or the last one to ensure the method always
    // returns something. This implements the interpreters behavior.
    if (statements.isEmpty()
        || !(statements.get(statements.size() - 1) instanceof ReturnStatement)) {
      code.add(new ByteCodeAppender.Simple(Runtime.GET_NONE, MethodReturn.REFERENCE));
    }
    // we now know which variables we used in the method, so assign them "undefined" (i.e. null)
    // at the beginning of the method
    code.set(0, scope.createLocalVariablesUndefined());
    // TODO(bazel-team) wrap ByteCodeAppender in our own type including a reference to the ASTNode
    // it came from and verify the stack and local variables ourselves, because ASM does not help
    // with debugging much when its stack map frame calculation fails because of invalid byte code
    return new Implementation.Simple(ByteCodeUtils.compoundAppender(code));
  }

  /**
   * Returns the location (filename:line) of the BaseFunction's definition.
   *
   * <p>If such a location is not defined, this method returns an empty string.
   */
  private String getLocationPathAndLine() {
    if (location == null) {
      return "";
    }

    StringBuilder builder = new StringBuilder();
    PathFragment path = location.getPath();
    if (path != null) {
      builder.append(path.getPathString());
    }

    LineAndColumn position = location.getStartLineAndColumn();
    if (position != null) {
      builder.append(":").append(position.getLine());
    }
    return builder.toString();
  }

  private void compilerDebug(String message) {
    System.err.println(message);
  }

  private void compilerDebug(String message, Throwable e) {
    compilerDebug(message);
    e.printStackTrace();
  }

  /**
   * A simple super class for all compiled function's classes.
   */
  protected abstract static class CompiledFunction {}

  /**
   * A {@link Textifier} for printing the generated byte code that keeps the ASM-internal label
   * names in place for easier debugging with IDE debuggers.
   */
  private static class DebugTextifier extends Textifier {
    DebugTextifier() {
      super(Opcodes.ASM5);
    }

    @Override
    protected void appendLabel(Label l) {
      buf.append(l.toString());
    }

    @Override
    protected Textifier createTextifier() {
      return new DebugTextifier();
    }
  }

  /**
   * Passes the {@link ClassWriter#COMPUTE_FRAMES} hint to ASM and optionally prints generated
   * byte code to System.err.
   */
  private static class StackMapFrameClassVisitor implements ClassVisitorWrapper {

    private final boolean debug;

    private StackMapFrameClassVisitor(boolean debug) {
      this.debug = debug;
    }

    @Override
    public int mergeWriter(int hint) {
      return hint | ClassWriter.COMPUTE_FRAMES;
    }

    @Override
    public int mergeReader(int hint) {
      return hint;
    }

    @Override
    public ClassVisitor wrap(ClassVisitor classVisitor) {
      if (debug) {
        return new TraceClassVisitor(
            classVisitor, new DebugTextifier(), new PrintWriter(System.err, true));
      } else {
        return classVisitor;
      }
    }
  }
}
