// Copyright (c) 2019, 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.naming.b124357885;

import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
import static com.android.tools.r8.utils.codeinspector.Matchers.isNotRenamed;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.graph.DexAnnotationElement;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.DexValue.DexValueArray;
import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.AnnotationSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class B124357885Test extends TestBase {
  public final boolean minification;

  @Parameterized.Parameters(name = "Minification: {0}")
  public static Boolean[] data() {
    return BooleanUtils.values();
  }

  public B124357885Test(boolean minification) {
    this.minification = minification;
  }

  private void checkSignatureAnnotation(CodeInspector inspector, AnnotationSubject signature) {
    DexAnnotationElement[] elements = signature.getAnnotation().elements;
    assertEquals(1, elements.length);
    assertEquals("value", elements[0].name.toString());
    assertTrue(elements[0].value instanceof DexValueArray);
    DexValueArray array = (DexValueArray) elements[0].value;
    StringBuilder builder = new StringBuilder();
    for (DexValue value : array.getValues()) {
      assertTrue(value instanceof DexValueString);
      builder.append(((DexValueString) value).value);
    }
    String fooImplFinalDescriptor =
        DescriptorUtils.javaTypeToDescriptor(inspector.clazz(FooImpl.class).getFinalName());
    StringBuilder expected =
        new StringBuilder()
            .append("()")
            // Remove the final ; from the descriptor to add the generic type.
            .append(fooImplFinalDescriptor.substring(0, fooImplFinalDescriptor.length() - 1))
            .append("<Ljava/lang/String;>")
            // Add the ; after the generic type.
            .append(";");
    assertEquals(expected.toString(), builder.toString());
  }

  @Test
  public void test() throws Exception {
    R8TestCompileResult compileResult = testForR8(Backend.DEX)
        .addProgramClasses(Main.class, Service.class, Foo.class, FooImpl.class)
        .addKeepMainRule(Main.class)
        .addKeepRules("-keepattributes Signature,InnerClasses,EnclosingMethod")
        .minification(minification)
        .compile()
        .inspect(inspector -> {
          assertThat(inspector.clazz(Main.class), isNotRenamed());
          assertThat(inspector.clazz(Service.class), isRenamed(minification));
          assertThat(inspector.clazz(Foo.class), not(isPresent()));
          assertThat(inspector.clazz(FooImpl.class), isRenamed(minification));
          // TODO(124477502): Using uniqueMethodWithName("fooList") does not work.
          assertEquals(1, inspector.clazz(Service.class).allMethods().size());
          MethodSubject fooList = inspector.clazz(Service.class).allMethods().get(0);
          AnnotationSubject signature = fooList.annotation("dalvik.annotation.Signature");
          checkSignatureAnnotation(inspector, signature);
        });

        String fooImplFinalName = compileResult.inspector().clazz(FooImpl.class).getFinalName();

        compileResult
            .run(Main.class)
            .assertSuccessWithOutput(StringUtils.lines(fooImplFinalName, fooImplFinalName));
  }
}

class Main {
  public static void main(String... args) throws Exception {
    Method method = Service.class.getMethod("fooList");
    ParameterizedType type = (ParameterizedType) method.getGenericReturnType();
    Class<?> rawType = (Class<?>) type.getRawType();
    System.out.println(rawType.getName());

    // Convince R8 we only use subtypes to get class merging of Foo into FooImpl.
    Foo<String> foo = new FooImpl<>();
    System.out.println(foo.getClass().getCanonicalName());
  }
}

interface Service {
  Foo<String> fooList();
}

interface Foo<T> {}

class FooImpl<T> implements Foo<T> {}
