// 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.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
import static org.hamcrest.CoreMatchers.allOf;
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.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;

public class B124357885Test extends TestBase {

  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")
        .compile()
        .inspect(inspector -> {
          assertThat(inspector.clazz(Main.class), allOf(isPresent(), not(isRenamed())));
          assertThat(inspector.clazz(Service.class), allOf(isPresent(), isRenamed()));
          assertThat(inspector.clazz(Foo.class), not(isPresent()));
          assertThat(inspector.clazz(FooImpl.class), allOf(isPresent(), isRenamed()));
          // 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> {}
