// Copyright (c) 2018, 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.maindexlist.whyareyoukeeping;

import static org.junit.Assert.assertEquals;

import com.android.tools.r8.GenerateMainDexList;
import com.android.tools.r8.GenerateMainDexListCommand;
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.shaking.WhyAreYouKeepingConsumer;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

class HelloWorldMain {
  public static void main(String[] args) {
    System.out.println(new MainDexClass());
  }
}

class MainDexClass {}

class NonMainDexClass {}

@RunWith(Parameterized.class)
public class MainDexListWhyAreYouKeeping extends TestBase {

  private static final List<Class<?>> CLASSES =
      ImmutableList.of(HelloWorldMain.class, MainDexClass.class, NonMainDexClass.class);

  private enum Command {
    R8,
    Generator
  }

  private enum ApiUse {
    WhyAreYouKeepingRule,
    KeptGraphConsumer
  }

  @Parameters(name = "{0} {1}")
  public static List<Object[]> parameters() {
    return buildParameters(Command.values(), ApiUse.values());
  }

  private final Command command;
  private final ApiUse apiUse;

  public MainDexListWhyAreYouKeeping(Command command, ApiUse apiUse) {
    this.command = command;
    this.apiUse = apiUse;
  }

  public void runTestWithGenerator(GraphConsumer consumer, String rule) throws Exception {
    GenerateMainDexListCommand.Builder builder =
        GenerateMainDexListCommand.builder()
            .addProgramFiles(ListUtils.map(CLASSES, ToolHelper::getClassFileForTestClass))
            .addLibraryFiles(ToolHelper.getDefaultAndroidJar())
            .addMainDexRules(
                ImmutableList.of(keepMainProguardConfiguration(HelloWorldMain.class)),
                Origin.unknown())
            .setMainDexKeptGraphConsumer(consumer);
    if (rule != null) {
      builder.addMainDexRules(ImmutableList.of(rule), Origin.unknown());
    }
    GenerateMainDexList.run(builder.build());
  }

  public void runTestWithR8(GraphConsumer consumer, String rule) throws Exception {
    R8FullTestBuilder builder =
        testForR8(Backend.DEX)
            .noTreeShaking()
            .noMinification()
            .setMinApi(AndroidApiLevel.K)
            .addProgramClasses(CLASSES)
            .addMainDexRules(keepMainProguardConfiguration(HelloWorldMain.class))
            .setMainDexKeptGraphConsumer(consumer)
            .allowStdoutMessages();
    if (rule != null) {
      builder.addMainDexRules(rule);
    }
    builder.compile();
  }

  private String runTest(Class<?> clazz) throws Exception {
    PrintStream stdout = System.out;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    String rule = null;
    WhyAreYouKeepingConsumer consumer = null;
    if (apiUse == ApiUse.KeptGraphConsumer) {
      consumer = new WhyAreYouKeepingConsumer(null);
    } else {
      assert apiUse == ApiUse.WhyAreYouKeepingRule;
      rule = "-whyareyoukeeping class " + clazz.getTypeName();
      System.setOut(new PrintStream(baos));
    }
    switch (command) {
      case R8:
        runTestWithR8(consumer, rule);
        break;
      case Generator:
        runTestWithGenerator(consumer, rule);
        break;
      default:
        throw new Unreachable();
    }
    if (consumer != null) {
      consumer.printWhyAreYouKeeping(Reference.classFromClass(clazz), new PrintStream(baos));
    } else {
      System.setOut(stdout);
    }
    return baos.toString();
  }

  @Test
  public void testMainDexClassWhyAreYouKeeping() throws Exception {
    String expected =
        StringUtils.lines(
            "com.android.tools.r8.maindexlist.whyareyoukeeping.MainDexClass",
            "|- is instantiated in:",
            "|  void " + HelloWorldMain.class.getTypeName() + ".main(java.lang.String[])",
            "|- is referenced in keep rule:",
            "|  -keep class " + HelloWorldMain.class.getTypeName() + " {",
            "|    public static void main(java.lang.String[]);",
            "|  }");
    assertEquals(expected, runTest(MainDexClass.class));
  }

  @Test
  public void testNonMainDexWhyAreYouKeeping() throws Exception {
    String expected =
        StringUtils.lines(
            "Nothing is keeping com.android.tools.r8.maindexlist.whyareyoukeeping.NonMainDexClass");
    assertEquals(expected, runTest(NonMainDexClass.class));
  }
}
