// Copyright (c) 2020, 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 com.android.tools.r8.annotations;

import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.enumunboxing.EnumUnboxingTestBase;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class AnnotationWithInjectedMethodsTest extends EnumUnboxingTestBase {

  private final TestParameters parameters;

  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters()
        .withAllRuntimes()
        .withApiLevelsStartingAtIncluding(apiLevelWithDefaultInterfaceMethodsSupport())
        .build();
  }

  public AnnotationWithInjectedMethodsTest(TestParameters parameters) {
    this.parameters = parameters;
  }

  @Test
  public void testRuntime() throws Exception {
    testForRuntime(parameters)
        .addProgramClasses(getProgramClasses())
        .addProgramClassFileData(getProgramClassFileData())
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutput(getExpectedOutput());
  }

  @Test
  public void testR8() throws Exception {
    testForR8(parameters.getBackend())
        .addProgramClasses(getProgramClasses())
        .addProgramClassFileData(getProgramClassFileData())
        .addKeepMainRule(Main.class)
        .addKeepClassAndMembersRules(AnnotationWithInjectedMethod.class)
        .addKeepRuntimeVisibleAnnotations()
        .addOptionsModification(options -> options.testing.allowInjectedAnnotationMethods = true)
        .noMinification()
        .setMinApi(parameters.getApiLevel())
        .compile()
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutput(getExpectedOutput());
  }

  private String getExpectedOutput() {
    ImmutableList.Builder<String> builder = ImmutableList.builder();
    builder.add(
        "Foo",
        "Bar",
        "Caught IncompleteAnnotationException: "
            + typeName(AnnotationWithInjectedMethod.class)
            + " missing element getInstanceData");
    if (parameters.isCfRuntime()) {
      builder.add("Caught AssertionError: Too many parameters for an annotation method");
    } else {
      builder.add(
          "Caught IllegalArgumentException: Invalid method for annotation type: "
              + "public "
              + (parameters.getRuntime().asDex().getVm().getVersion() == Version.V7_0_0
                  ? ""
                  : "default ")
              + typeName(Data.class)
              + " "
              + typeName(AnnotationWithInjectedMethod.class)
              + ".getInstanceData("
              + typeName(Data.class)
              + ")");
    }
    return StringUtils.lines(builder.build());
  }

  private Collection<Class<?>> getProgramClasses() {
    return ImmutableList.of(Data.class);
  }

  private Collection<byte[]> getProgramClassFileData() throws IOException {
    return ImmutableList.of(
        transformer(Main.class)
            .replaceAnnotationDescriptor(
                descriptor(ToBeAnnotationWithInjectedMethod.class),
                descriptor(AnnotationWithInjectedMethod.class))
            .transform(),
        transformer(AnnotationWithInjectedMethod.class)
            .setAnnotation()
            .removeInnerClasses()
            .replaceAnnotationDescriptor(
                descriptor(ToBeRetention.class), descriptor(Retention.class))
            .transform());
  }

  static class Data {

    String value;

    Data(String value) {
      this.value = value;
    }

    @Override
    public String toString() {
      return value;
    }
  }

  @Retention(RetentionPolicy.RUNTIME)
  @interface ToBeRetention {
    RetentionPolicy value();
  }

  @ToBeRetention(RetentionPolicy.RUNTIME)
  /*@*/ interface AnnotationWithInjectedMethod extends Annotation {

    default Data getInstanceData() {
      return new Data("Baz");
    }

    default Data getInstanceData(Data in) {
      return new Data(in.value);
    }

    static Data getStaticData() {
      return new Data("Foo");
    }

    static Data getStaticData(Data in) {
      return new Data(in.value);
    }
  }

  @Retention(RetentionPolicy.RUNTIME)
  @interface ToBeAnnotationWithInjectedMethod {}

  @ToBeAnnotationWithInjectedMethod
  static class Main {

    public static void main(String[] args) {
      System.out.println(AnnotationWithInjectedMethod.getStaticData());
      System.out.println(AnnotationWithInjectedMethod.getStaticData(new Data("Bar")));

      try {
        System.out.println(getAnnotationWithInjectedMethod().getInstanceData());
      } catch (Throwable e) {
        System.out.println("Caught " + e.getClass().getSimpleName() + ": " + e.getMessage());
      }

      try {
        System.out.println(getAnnotationWithInjectedMethod().getInstanceData(new Data("Qux")));
      } catch (Throwable e) {
        System.out.println("Caught " + e.getClass().getSimpleName() + ": " + e.getMessage());
      }
    }

    static AnnotationWithInjectedMethod getAnnotationWithInjectedMethod() {
      return Main.class.getAnnotation(AnnotationWithInjectedMethod.class);
    }
  }
}
