// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package invokecustom2;

import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Arrays;
import java.util.List;

abstract class Super {
  public void targetMethodTest4() {
    System.out.println("targetMethodTest4 from Super");
  }

  public abstract void helperMethodTest9();
}

public class InvokeCustom extends Super implements Runnable {

  public InvokeCustom() {}
  public InvokeCustom(int i) {
    System.out.println("InvokeCustom.<init>(" + i + ")");
  }

  private static void targetMethodTest1() {
    System.out.println("Hello World!");
  }

  private static void targetMethodTest2(boolean z, byte b, char c, short s, int i, float f, long l,
      double d, String str) {
    System.out.println(z);
    System.out.println(b);
    System.out.println(c);
    System.out.println(s);
    System.out.println(i);
    System.out.println(f);
    System.out.println(l);
    System.out.println(d);
    System.out.println(str);
  }

  private static void targetMethodTest3() {
    System.out.println("targetMethodTest3 from InvokeCustom");
  }

  @Override
  public void targetMethodTest4() {
    // The generated code should be calling Super.targetMethodTest4.
    System.out.println("targetMethodTest4 from InvokeCustom (oops!)");
  }

  public static int targetMethodTest5(int x, int y, int total) {
    int calculated = x + y;
    System.out.println("targetMethodTest5 " + x + " + " + y + " = " + calculated);
    if (calculated != total) {
      System.out.println("Failed " + calculated + " != " + total);
    }
    return calculated;
  }

  public static long targetMethodTest6(long x, long y, long total) {
    long calculated = x + y;
    System.out.println("targetMethodTest6 " + x + " + " + y + " = " + calculated);
    if (calculated != total) {
      System.out.println("Failed " + calculated + " != " + total);
    }
    return calculated;
  }

  public static double targetMethodTest7(float x, float y, double product) {
    double calculated = x * y;
    System.out.println("targetMethodTest7 " + x + " * " + y + " = " + calculated);
    if (calculated != product) {
      System.out.println("Failed " + calculated + " != " + product);
    }
    return calculated;
  }

  public static void targetMethodTest8(String s) {
    System.out.println("targetMethodTest8 " + s);
  }

  private static int staticFieldTest9 = 0;

  private static void checkStaticFieldTest9(MethodHandle getter, MethodHandle setter)
      throws Throwable {
    final int NEW_VALUE = 0x76543210;
    int oldValue = (int) getter.invokeExact();
    setter.invokeExact(NEW_VALUE);
    int newValue = (int) getter.invokeExact();
    System.out.print("checkStaticFieldTest9: old " + oldValue + " new " + newValue +
        " expected " + NEW_VALUE + " ");
    System.out.println((newValue == NEW_VALUE) ? "OK" : "ERROR");
  }

  private float fieldTest9 = 0.0f;

  private void checkFieldTest9(MethodHandle getter, MethodHandle setter)
      throws Throwable {
    final float NEW_VALUE = 1.99e-19f;
    float oldValue = (float) getter.invokeExact(this);
    setter.invokeExact(this, NEW_VALUE);
    float newValue = (float) getter.invokeExact(this);
    System.out.print("checkFieldTest9: old " + oldValue + " new " + newValue +
        " expected " + NEW_VALUE + " ");
    System.out.println((newValue == NEW_VALUE) ? "OK" : "ERROR");
  }

  public void helperMethodTest9() {
    System.out.println("helperMethodTest9 in " + InvokeCustom.class);
  }

  private static void targetMethodTest9() {
    System.out.println("targetMethodTest9()");
  }

  public void run() {
    System.out.println("run() for Test9");
  }

  public static CallSite bsmLookupStatic(MethodHandles.Lookup caller, String name, MethodType type)
      throws NoSuchMethodException, IllegalAccessException {
    System.out.println("bsmLookupStatic []");
    final MethodHandles.Lookup lookup = MethodHandles.lookup();
    final MethodHandle targetMH = lookup.findStatic(lookup.lookupClass(), name, type);
    return new ConstantCallSite(targetMH.asType(type));
  }

  public static CallSite bsmLookupStaticWithExtraArgs(
      MethodHandles.Lookup caller, String name, MethodType type, int i, long l, float f, double d)
      throws NoSuchMethodException, IllegalAccessException {
    System.out.println("bsmLookupStaticWithExtraArgs [" + i + ", " + l + ", " + f + ", " + d + "]");
    final MethodHandles.Lookup lookup = MethodHandles.lookup();
    final MethodHandle targetMH = lookup.findStatic(lookup.lookupClass(), name, type);
    return new ConstantCallSite(targetMH.asType(type));
  }

  public static CallSite bsmCreateCallSite(
      MethodHandles.Lookup caller, String name, MethodType type, MethodHandle mh)
      throws Throwable {
    System.out.println("bsmCreateCallSite [" + mh + "]");
    return new ConstantCallSite(mh);
  }

  private void privateMethodTest9() {
    System.out.println("InvokeCustom.privateMethodTest9()");
  }

  public static CallSite bsmLookupTest9(MethodHandles.Lookup caller, String name, MethodType type,
      MethodHandle staticGetter,  MethodHandle staticSetter,
      MethodHandle fieldGetter, MethodHandle fieldSetter,
      MethodHandle instanceInvoke, MethodHandle constructor,
      MethodHandle interfaceInvoke, MethodHandle privateInvoke)
      throws Throwable {
    System.out.println("bsmLookupTest9 [" + staticGetter + ", " + staticSetter + ", " +
        fieldGetter + ", " + fieldSetter + "]");
    System.out.println(name + " " + type);

    // Check constant method handles passed can be invoked.
    checkStaticFieldTest9(staticGetter, staticSetter);
    InvokeCustom instance = new InvokeCustom();
    instance.checkFieldTest9(fieldGetter, fieldSetter);

    // Check virtual method.
    instanceInvoke.invokeExact(instance);

    InvokeCustom instance2 = (InvokeCustom) constructor.invokeExact(3);
    interfaceInvoke.invoke(instance2);
    privateInvoke.invoke(instance2);

    final MethodHandles.Lookup lookup = MethodHandles.lookup();
    final MethodHandle targetMH = lookup.findStatic(lookup.lookupClass(), name, type);
    return new ConstantCallSite(targetMH.asType(type));
  }

  public static void lambdaTest() {
    List<String> strings = Arrays.asList(new String[] { "Three", "One", "FortyTwo" });
    String sample = strings.stream().filter(x -> "One".equals(x.trim()))
        .map(String::trim).findAny().orElse("");
    strings.stream().forEach(System.out::println);
  }
}