// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.android;

import static com.google.common.truth.Truth.assertThat;

import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.FileTime;
import java.util.Collections;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Tests for {@link RClassGeneratorAction}.
 */
@RunWith(JUnit4.class)
public class RClassGeneratorActionTest {

  private Path tempDir;

  @Before
  public void setUp() throws IOException {
    tempDir = Files.createTempDirectory(toString());
  }

  /**
   * TODO(jvoung): use {@link AndroidDataBuilder} instead, once that's moved to this source tree.
   * This is a slimmed down version used to avoid dependencies.
   */
  private static class ManifestBuilder {

    private final Path root;

    private ManifestBuilder(Path root) {
      this.root = root;
    }

    public static ManifestBuilder of(Path root) {
      return new ManifestBuilder(root);
    }

    public Path createManifest(String path, String manifestPackage, String... lines)
        throws IOException {
      Path manifest = root.resolve(path);
      Files.createDirectories(root);
      Files.write(manifest,
          String.format(
              "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                  + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" "
                  + " package=\"%s\">"
                  + "%s</manifest>",
              manifestPackage,
              Joiner.on("\n").join(lines)).getBytes(StandardCharsets.UTF_8));
      return manifest;
    }
  }

  @Test
  public void withBinaryAndLibraries() throws Exception {
    Path binaryManifest = ManifestBuilder.of(tempDir.resolve("binary"))
        .createManifest("AndroidManifest.xml", "com.google.app",
            "<application android:name=\"com.google.app\">",
            "<activity android:name=\"com.google.bar.activityFoo\" />",
            "</application>");
    Path libFooManifest = ManifestBuilder.of(tempDir.resolve("libFoo"))
        .createManifest("AndroidManifest.xml", "com.google.foo", "");
    Path libBarManifest = ManifestBuilder.of(tempDir.resolve("libBar"))
        .createManifest("AndroidManifest.xml", "com.google.bar", "");

    Path binarySymbols = createFile("R.txt",
        "int attr agility 0x7f010000",
        "int attr dexterity 0x7f010001",
        "int drawable heart 0x7f020000",
        "int id someTextView 0x7f080000",
        "int integer maxNotifications 0x7f090000",
        "int string alphabet 0x7f100000",
        "int string ok 0x7f100001");
    Path libFooSymbols = createFile("libFoo.R.txt",
        "int attr agility 0x1",
        "int id someTextView 0x1",
        "int string ok 0x1");
    Path libBarSymbols = createFile("libBar.R.txt",
        "int attr dexterity 0x1",
        "int drawable heart 0x1");

    Path jarPath = tempDir.resolve("app_resources.jar");

    RClassGeneratorAction.main(
        ImmutableList.<String>of(
                "--primaryRTxt",
                binarySymbols.toString(),
                "--primaryManifest",
                binaryManifest.toString(),
                "--library",
                libFooSymbols + "," + libFooManifest,
                "--library",
                libBarSymbols + "," + libBarManifest,
                "--classJarOutput",
                jarPath.toString())
            .toArray(new String[0]));

    assertThat(Files.exists(jarPath)).isTrue();
    assertThat(Files.getLastModifiedTime(jarPath)).isEqualTo(FileTime.fromMillis(0));

    try (ZipFile zip = new ZipFile(jarPath.toFile())) {
      List<? extends ZipEntry> zipEntries = Collections.list(zip.entries());
      Iterable<String> entries = getZipFilenames(zipEntries);
      assertThat(entries)
          .containsExactly(
              "com/google/foo/R$attr.class",
              "com/google/foo/R$id.class",
              "com/google/foo/R$string.class",
              "com/google/foo/R.class",
              "com/google/bar/R$attr.class",
              "com/google/bar/R$drawable.class",
              "com/google/bar/R.class",
              "com/google/app/R$attr.class",
              "com/google/app/R$drawable.class",
              "com/google/app/R$id.class",
              "com/google/app/R$integer.class",
              "com/google/app/R$string.class",
              "com/google/app/R.class",
              "META-INF/MANIFEST.MF");
    }
  }

  @Test
  public void withNoBinaryAndLibraries() throws Exception {
    Path libFooManifest =
        ManifestBuilder.of(tempDir.resolve("libFoo"))
            .createManifest("AndroidManifest.xml", "com.google.foo", "");
    Path libBarManifest =
        ManifestBuilder.of(tempDir.resolve("libBar"))
            .createManifest("AndroidManifest.xml", "com.google.bar", "");

    Path libFooSymbols =
        createFile(
            "libFoo.R.txt", "int attr agility 0x1", "int id someTextView 0x1", "int string ok 0x1");
    Path libBarSymbols =
        createFile("libBar.R.txt", "int attr dexterity 0x1", "int drawable heart 0x1");

    Path jarPath = tempDir.resolve("app_resources.jar");

    RClassGeneratorAction.main(
        ImmutableList.<String>of(
                "--library",
                libFooSymbols + "," + libFooManifest,
                "--library",
                libBarSymbols + "," + libBarManifest,
                "--classJarOutput",
                jarPath.toString())
            .toArray(new String[0]));

    assertThat(Files.exists(jarPath)).isTrue();
    assertThat(Files.getLastModifiedTime(jarPath)).isEqualTo(FileTime.fromMillis(0));

    try (ZipFile zip = new ZipFile(jarPath.toFile())) {
      List<? extends ZipEntry> zipEntries = Collections.list(zip.entries());
      Iterable<String> entries = getZipFilenames(zipEntries);
      assertThat(entries)
          .containsExactly(
              "com/google/foo/R$attr.class",
              "com/google/foo/R$id.class",
              "com/google/foo/R$string.class",
              "com/google/foo/R.class",
              "com/google/bar/R$attr.class",
              "com/google/bar/R$drawable.class",
              "com/google/bar/R.class",
              "META-INF/MANIFEST.MF");
    }
  }

  @Test
  public void withBinaryNoLibraries() throws Exception {
    Path binaryManifest = ManifestBuilder.of(tempDir.resolve("binary"))
        .createManifest("AndroidManifest.xml", "com.google.app",
            "<application android:name=\"com.google.app\">",
            "<activity android:name=\"com.google.bar.activityFoo\" />",
            "</application>");

    Path binarySymbols = createFile("R.txt",
        "int attr agility 0x7f010000",
        "int attr dexterity 0x7f010001",
        "int drawable heart 0x7f020000",
        "int id someTextView 0x7f080000",
        "int integer maxNotifications 0x7f090000",
        "int string alphabet 0x7f100000",
        "int string ok 0x7f100001");

    Path jarPath = tempDir.resolve("app_resources.jar");

    RClassGeneratorAction.main(ImmutableList.<String>of(
        "--primaryRTxt", binarySymbols.toString(),
        "--primaryManifest", binaryManifest.toString(),
        "--classJarOutput", jarPath.toString()
    ).toArray(new String[0]));

    assertThat(Files.exists(jarPath)).isTrue();
    assertThat(Files.getLastModifiedTime(jarPath)).isEqualTo(FileTime.fromMillis(0));

    try (ZipFile zip = new ZipFile(jarPath.toFile())) {
      List<? extends ZipEntry> zipEntries = Collections.list(zip.entries());
      Iterable<String> entries = getZipFilenames(zipEntries);
      assertThat(entries)
          .containsExactly(
              "com/google/app/R$attr.class",
              "com/google/app/R$drawable.class",
              "com/google/app/R$id.class",
              "com/google/app/R$integer.class",
              "com/google/app/R$string.class",
              "com/google/app/R.class",
              "META-INF/MANIFEST.MF");
    }
  }

  @Test
  public void noBinary() throws Exception {
    Path jarPath = tempDir.resolve("app_resources.jar");
    RClassGeneratorAction.main(ImmutableList.<String>of(
        "--classJarOutput", jarPath.toString()
    ).toArray(new String[0]));

    assertThat(Files.exists(jarPath)).isTrue();
    assertThat(Files.getLastModifiedTime(jarPath)).isEqualTo(FileTime.fromMillis(0));

    try (ZipFile zip = new ZipFile(jarPath.toFile())) {
      List<? extends ZipEntry> zipEntries = Collections.list(zip.entries());
      Iterable<String> entries = getZipFilenames(zipEntries);
      assertThat(entries).containsExactly("META-INF/MANIFEST.MF");
    }
  }

  @Test
  public void customPackageForR() throws Exception {
    Path binaryManifest = ManifestBuilder.of(tempDir.resolve("binary"))
        .createManifest("AndroidManifest.xml", "com.google.app",
            "<application android:name=\"com.google.app\">",
            "<activity android:name=\"com.google.foo.activityFoo\" />",
            "</application>");
    Path libFooManifest = ManifestBuilder.of(tempDir.resolve("libFoo"))
        .createManifest("AndroidManifest.xml", "com.google.foo", "");

    Path binarySymbols = createFile("R.txt",
        "int attr agility 0x7f010000",
        "int integer maxNotifications 0x7f090000",
        "int string ok 0x7f100001");
    Path libFooSymbols = createFile("libFoo.R.txt",
        "int string ok 0x1");
    Path jarPath = tempDir.resolve("app_resources.jar");
    RClassGeneratorAction.main(
        ImmutableList.<String>of(
                "--primaryRTxt",
                binarySymbols.toString(),
                "--primaryManifest",
                binaryManifest.toString(),
                "--packageForR",
                "com.custom.er",
                "--library",
                libFooSymbols + "," + libFooManifest,
                "--classJarOutput",
                jarPath.toString())
            .toArray(new String[0]));

    assertThat(Files.exists(jarPath)).isTrue();
    assertThat(Files.getLastModifiedTime(jarPath)).isEqualTo(FileTime.fromMillis(0));

    try (ZipFile zip = new ZipFile(jarPath.toFile())) {
      List<? extends ZipEntry> zipEntries = Collections.list(zip.entries());
      Iterable<String> entries = getZipFilenames(zipEntries);
      assertThat(entries)
          .containsExactly(
              "com/google/foo/R$string.class",
              "com/google/foo/R.class",
              "com/custom/er/R$attr.class",
              "com/custom/er/R$integer.class",
              "com/custom/er/R$string.class",
              "com/custom/er/R.class",
              "META-INF/MANIFEST.MF");
    }
  }

  @Test
  public void noSymbolsNoRClass() throws Exception {
    Path binaryManifest = ManifestBuilder.of(tempDir.resolve("binary"))
        .createManifest("AndroidManifest.xml", "com.google.app",
            "<application android:name=\"com.google.app\">",
            "<activity android:name=\"com.google.foo.activityFoo\" />",
            "</application>");

    Path binarySymbols = createFile("R.txt", "");
    Path jarPath = tempDir.resolve("app_resources.jar");
    RClassGeneratorAction.main(
        ImmutableList.<String>of(
            "--primaryRTxt",
            binarySymbols.toString(),
            "--primaryManifest",
            binaryManifest.toString(),
            "--classJarOutput",
            jarPath.toString())
            .toArray(new String[0]));

    assertThat(Files.exists(jarPath)).isTrue();
    assertThat(Files.getLastModifiedTime(jarPath)).isEqualTo(FileTime.fromMillis(0));

    try (ZipFile zip = new ZipFile(jarPath.toFile())) {
      List<? extends ZipEntry> zipEntries = Collections.list(zip.entries());
      Iterable<String> entries = getZipFilenames(zipEntries);
      assertThat(entries).containsExactly("META-INF/MANIFEST.MF");
    }
  }

  private Path createFile(String name, String... contents) throws IOException {
    Path path = tempDir.resolve(name);
    Files.createDirectories(path.getParent());
    Files.newOutputStream(path).write(
        Joiner.on("\n").join(contents).getBytes(StandardCharsets.UTF_8));
    return path;
  }

  private Iterable<String> getZipFilenames(Iterable<? extends ZipEntry> entries) {
    return Iterables.transform(entries,
        new Function<ZipEntry, String>() {
          @Override
          public String apply(ZipEntry input) {
            return input.getName();
          }
        });
  }
}
