// 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.naming;

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

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.DataDirectoryResource;
import com.android.tools.r8.DataEntryResource;
import com.android.tools.r8.DataResourceConsumer;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import org.junit.Ignore;
import org.junit.Test;

public class AdaptResourceFileContentsTest extends TestBase {

  private static class CustomDataResourceConsumer implements DataResourceConsumer {

    private final Map<String, ImmutableList<String>> resources = new HashMap<>();

    @Override
    public void accept(DataDirectoryResource directory, DiagnosticsHandler diagnosticsHandler) {
      throw new Unreachable();
    }

    @Override
    public void accept(DataEntryResource file, DiagnosticsHandler diagnosticsHandler) {
      try {
        byte[] bytes = ByteStreams.toByteArray(file.getByteStream());
        String contents = new String(bytes, Charset.defaultCharset());
        resources.put(file.getName(), ImmutableList.copyOf(contents.split(System.lineSeparator())));
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }

    @Override
    public void finished(DiagnosticsHandler handler) {}

    public ImmutableList<String> get(String name) {
      return resources.get(name);
    }
  }

  private static final ImmutableList<String> originalAllChangedResource =
      ImmutableList.of(
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A<java.lang.String>",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A<"
              + "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A>",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          // Test property values are rewritten.
          "property=com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A",
          // Test XML content is rewritten.
          "<tag>com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A</tag>",
          "<tag attr=\"com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A\"></tag>",
          // Test single-quote literals are rewritten.
          "'com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A'");

  private static final ImmutableList<String> originalAllPresentResource =
      ImmutableList.of(
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B");

  private static final ImmutableList<String> originalAllUnchangedResource =
      ImmutableList.of(
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass",
          // Test there is no renaming for the method on A.
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A.method",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A.method()",
          // Test there is no renaming for the methods on B.
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B.method",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B.method()",
          // Test various prefixes.
          "42com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          "WithIdentifierPrefixcom.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          "-com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          "WithDashPrefix-com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          "$com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          "WithDollarPrefix$com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          ".com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          "WithDotPrefix.com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          // Test various suffixes.
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B42",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$BWithIdentifierSuffix",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B-",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B-WithDashSuffix",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B$",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B$WithDollarSuffix",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B.",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B.WithDotSuffix");

  private static String getProguardConfig(
      boolean enableAdaptResourceFileContents, String adaptResourceFileContentsPathFilter) {
    String adaptResourceFileContentsRule;
    if (enableAdaptResourceFileContents) {
      adaptResourceFileContentsRule = "-adaptresourcefilecontents";
      if (adaptResourceFileContentsPathFilter != null) {
        adaptResourceFileContentsRule += " " + adaptResourceFileContentsPathFilter;
      }
    } else {
      adaptResourceFileContentsRule = "";
    }
    return String.join(
        System.lineSeparator(),
        adaptResourceFileContentsRule,
        "-keep class " + AdaptResourceFileContentsTestClass.class.getName() + " {",
        "  public static void main(...);",
        "}",
        "-neverinline class com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B {",
        "  public void method();",
        "}");
  }

  @Test
  public void testEnabled() throws Exception {
    CustomDataResourceConsumer dataResourceConsumer = new CustomDataResourceConsumer();
    AndroidApp out = compileWithR8(getProguardConfig(true, null), dataResourceConsumer);

    // Check that the data resources have changed as expected.
    checkAllAreChanged(
        dataResourceConsumer.get("resource-all-changed.md"), originalAllChangedResource);
    checkAllAreChanged(
        dataResourceConsumer.get("resource-all-changed.txt"), originalAllChangedResource);

    // Check that the new names are consistent with the actual application code.
    checkAllArePresent(
        dataResourceConsumer.get("resource-all-present.txt"), new CodeInspector(out));

    // Check that the data resources have not changed unexpectedly.
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.class"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.cLaSs"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-unchanged.txt"), originalAllUnchangedResource);
  }

  @Ignore("b/36847655")
  @Test
  public void testProguardBehavior() throws Exception {
    // TODO(christofferqa): Run Proguard on the example and check that R8 behaves the same way.
  }

  @Test
  public void testEnabledWithFilter() throws Exception {
    CustomDataResourceConsumer dataResourceConsumer = new CustomDataResourceConsumer();
    compileWithR8(getProguardConfig(true, "*.md"), dataResourceConsumer);

    // Check that the file matching the filter has changed as expected.
    checkAllAreChanged(
        dataResourceConsumer.get("resource-all-changed.md"), originalAllChangedResource);

    // Check that all the other data resources are unchanged.
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.class"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.cLaSs"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.txt"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-present.txt"), originalAllPresentResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-unchanged.txt"), originalAllUnchangedResource);
  }

  @Test
  public void testDisabled() throws Exception {
    CustomDataResourceConsumer dataResourceConsumer = new CustomDataResourceConsumer();
    compileWithR8(getProguardConfig(false, null), dataResourceConsumer);

    // Check that all data resources are unchanged.
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.class"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.cLaSs"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.md"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.txt"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-present.txt"), originalAllPresentResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-unchanged.txt"), originalAllUnchangedResource);
  }

  private static void checkAllAreChanged(
      ImmutableList<String> adaptedLines, ImmutableList<String> originalLines) {
    assertEquals(adaptedLines.size(), originalLines.size());
    for (int i = 0; i < originalLines.size(); i++) {
      assertNotEquals(originalLines.get(i), adaptedLines.get(i));
    }
  }

  private static void checkAllArePresent(ImmutableList<String> lines, CodeInspector inspector) {
    for (String line : lines) {
      assertThat(inspector.clazz(line), isPresent());
    }
  }

  private static void checkAllAreUnchanged(
      ImmutableList<String> adaptedLines, ImmutableList<String> originalLines) {
    assertEquals(adaptedLines.size(), originalLines.size());
    for (int i = 0; i < originalLines.size(); i++) {
      assertEquals(originalLines.get(i), adaptedLines.get(i));
    }
  }

  private AndroidApp compileWithR8(String proguardConfig, DataResourceConsumer dataResourceConsumer)
      throws CompilationFailedException, IOException {
    AndroidApp app =
        AndroidApp.builder()
            .addProgramFiles(
                ToolHelper.getClassFileForTestClass(AdaptResourceFileContentsTestClass.class),
                ToolHelper.getClassFileForTestClass(AdaptResourceFileContentsTestClass.A.class),
                ToolHelper.getClassFileForTestClass(AdaptResourceFileContentsTestClass.B.class))
            .addDataResource(
                String.join(System.lineSeparator(), originalAllChangedResource).getBytes(),
                "resource-all-changed.class",
                Origin.unknown())
            .addDataResource(
                String.join(System.lineSeparator(), originalAllChangedResource).getBytes(),
                "resource-all-changed.cLaSs",
                Origin.unknown())
            .addDataResource(
                String.join(System.lineSeparator(), originalAllChangedResource).getBytes(),
                "resource-all-changed.md",
                Origin.unknown())
            .addDataResource(
                String.join(System.lineSeparator(), originalAllChangedResource).getBytes(),
                "resource-all-changed.txt",
                Origin.unknown())
            .addDataResource(
                String.join(System.lineSeparator(), originalAllPresentResource).getBytes(),
                "resource-all-present.txt",
                Origin.unknown())
            .addDataResource(
                String.join(System.lineSeparator(), originalAllUnchangedResource).getBytes(),
                "resource-all-unchanged.txt",
                Origin.unknown())
            .build();
    R8Command command =
        ToolHelper.allowTestProguardOptions(
                ToolHelper.prepareR8CommandBuilder(app)
                    .addProguardConfiguration(ImmutableList.of(proguardConfig), Origin.unknown()))
            .build();
    return ToolHelper.runR8(
        command,
        options -> {
          // TODO(christofferqa): Class inliner should respect -neverinline.
          options.enableClassInlining = false;
          options.enableClassMerging = true;
          options.dataResourceConsumer = dataResourceConsumer;
        });
  }
}

class AdaptResourceFileContentsTestClass {

  public static void main(String[] args) {
    B obj = new B();
    obj.method();
  }

  static class A {

    public void method() {
      System.out.println("In A.method()");
    }
  }

  static class B extends A {

    public void method() {
      System.out.println("In B.method()");
      super.method();
    }
  }
}
