// 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.ir.optimize.unusedarguments;

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
import java.util.List;
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 UnusedArgumentsCollisionMappingTest extends TestBase {

  private final TestParameters parameters;
  private final CompilationMode compilationMode;

  @Parameters(name = "{0}, compilation mode: {1}")
  public static List<Object[]> data() {
    return buildParameters(
        getTestParameters().withAllRuntimesAndApiLevels().build(), CompilationMode.values());
  }

  public UnusedArgumentsCollisionMappingTest(
      TestParameters parameters, CompilationMode compilationMode) {
    this.parameters = parameters;
    this.compilationMode = compilationMode;
  }

  @Test
  public void testR8() throws Exception {
    R8TestRunResult runResult =
        testForR8(parameters.getBackend())
            .setMode(compilationMode)
            .addProgramClasses(Main.class)
            .setMinApi(parameters.getApiLevel())
            .addKeepMainRule(Main.class)
            .enableInliningAnnotations()
            .addKeepAttributeLineNumberTable()
            .run(parameters.getRuntime(), Main.class)
            .assertSuccessWithOutputLines("test with unused", "test with used: foo")
            .inspect(this::verifyArgumentsRemoved);
    assertEquals(
        1,
        StringUtils.splitLines(runResult.proguardMap()).stream()
            .filter(line -> line.contains("void test(java.lang.String,java.lang.String)"))
            .count());
    assertEquals(
        1,
        StringUtils.splitLines(runResult.proguardMap()).stream()
            .filter(line -> line.contains("void test(java.lang.String)"))
            .count());
  }

  private void verifyArgumentsRemoved(CodeInspector inspector) {
    ClassSubject main = inspector.clazz(Main.class);
    assertThat(main, isPresent());
    List<FoundMethodSubject> foundMethodSubjects = main.allMethods();
    assertEquals(3, foundMethodSubjects.size());
    boolean foundZeroArgumentMethod = false;
    boolean foundOneArgumentMethod = false;
    for (FoundMethodSubject method : foundMethodSubjects) {
      if (method.getFinalName().equals("main")) {
        continue;
      }
      foundZeroArgumentMethod |= method.getMethod().parameters().size() == 0;
      foundOneArgumentMethod |= method.getMethod().parameters().size() == 1;
    }
    assertTrue(foundZeroArgumentMethod);
    assertTrue(foundOneArgumentMethod);
  }

  public static class Main {

    @NeverInline
    public static void test(String unused) {
      System.out.println("test with unused");
    }

    @NeverInline
    public static void test(String used, String unused) {
      System.out.println("test with used: " + used);
    }

    public static void main(String[] args) {
      test("foo");
      test("foo", "notused");
    }
  }
}
