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

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

import com.android.SdkConstants;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryStream;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.concurrent.ExecutionException;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Tests for {@link RClassGenerator}.
 */
@RunWith(JUnit4.class)
public class RClassGeneratorTest {

  private Path temp;
  @Rule
  public final ExpectedException thrown = ExpectedException.none();

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

  @Test
  public void plainInts() throws Exception {
    checkSimpleInts(true);
  }

  @Test
  public void nonFinalFields() throws Exception {
    checkSimpleInts(false);
  }

  private void checkSimpleInts(boolean finalFields) throws Exception {
    // R.txt with the real IDs after linking together libraries.
    ResourceSymbols symbolValues =
        createSymbolFile(
            "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");
    // R.txt for the library, where the values are not the final ones (so ignore them). We only use
    // this to keep the # of inner classes small (exactly the set needed by the library).
    ResourceSymbols symbolsInLibrary =
        createSymbolFile(
            "lib.R.txt", "int attr agility 0x1", "int id someTextView 0x1", "int string ok 0x1");
    Path out = temp.resolve("classes");
    Files.createDirectories(out);
    RClassGenerator writer = RClassGenerator.with(out, symbolValues.asInitializers(), finalFields);
    writer.write("com.bar", symbolsInLibrary.asInitializers());

    Path packageDir = out.resolve("com/bar");
    checkFilesInPackage(packageDir, "R.class", "R$attr.class", "R$id.class", "R$string.class");
    Class<?> outerClass = checkTopLevelClass(out,
        "com.bar.R",
        "com.bar.R$attr",
        "com.bar.R$id",
        "com.bar.R$string");
    checkInnerClass(out,
        "com.bar.R$attr",
        outerClass,
        ImmutableMap.of("agility", 0x7f010000),
        ImmutableMap.<String, List<Integer>>of(),
        finalFields
    );
    checkInnerClass(out,
        "com.bar.R$id",
        outerClass,
        ImmutableMap.of("someTextView", 0x7f080000),
        ImmutableMap.<String, List<Integer>>of(),
        finalFields
    );
    checkInnerClass(out,
        "com.bar.R$string",
        outerClass,
        ImmutableMap.of("ok", 0x7f100001),
        ImmutableMap.<String, List<Integer>>of(),
        finalFields
    );
  }

  @Test
  public void checkFileWriteThrowsOnExisting() throws Exception {
    checkFileWriteThrowsOnExisting(SdkConstants.FN_COMPILED_RESOURCE_CLASS);
  }

  @Test
  public void checkInnerFileWriteThrowsOnExisting() throws Exception {
    checkFileWriteThrowsOnExisting("R$string.class");
  }

  private void checkFileWriteThrowsOnExisting(String existingFile) throws Exception {
    ResourceSymbols symbolValues =
        createSymbolFile("R.txt", "int string ok 0x7f100001");
    ResourceSymbols symbolsInLibrary =
        createSymbolFile("lib.R.txt", "int string ok 0x1");

    Path out = temp.resolve("classes");
    String packageName = "com";
    Path packageFolder = out.resolve(packageName);
    Files.createDirectories(packageFolder);

    RClassGenerator writer = RClassGenerator.with(out, symbolValues.asInitializers(), false);
    Files.write(packageFolder.resolve(existingFile), new byte[0]);

    try {
      writer.write(packageName, symbolsInLibrary.asInitializers());
    } catch (FileAlreadyExistsException e) {
      return;
    }
    throw new Exception("Expected to throw a FileAlreadyExistsException");
  }

  @Test
  public void emptyIntArrays() throws Exception {
    boolean finalFields = true;
    // Make sure we parse an empty array the way the R.txt writes it.
    ResourceSymbols symbolValues = createSymbolFile("R.txt", "int[] styleable ActionMenuView { }");
    ResourceSymbols symbolsInLibrary = symbolValues;
    Path out = temp.resolve("classes");
    Files.createDirectories(out);
    RClassGenerator writer = RClassGenerator.with(out, symbolValues.asInitializers(), finalFields);
    writer.write("com.testEmptyIntArray", symbolsInLibrary.asInitializers());

    Path packageDir = out.resolve("com/testEmptyIntArray");
    checkFilesInPackage(packageDir, "R.class", "R$styleable.class");
    Class<?> outerClass = checkTopLevelClass(out,
        "com.testEmptyIntArray.R",
        "com.testEmptyIntArray.R$styleable");
    checkInnerClass(out,
        "com.testEmptyIntArray.R$styleable",
        outerClass,
        ImmutableMap.<String, Integer>of(),
        ImmutableMap.<String, List<Integer>>of(
            "ActionMenuView", ImmutableList.<Integer>of()
        ),
        finalFields
    );
  }

  static final Matcher<Throwable> NUMBER_FORMAT_EXCEPTION =
      new BaseMatcher<Throwable>() {
        @Override
        public boolean matches(Object item) {
          if (item instanceof NumberFormatException) {
            return true;
          }
          return false;
        }

        @Override
        public void describeTo(Description description) {
          description.appendText(NumberFormatException.class.toString());
        }
      };

  @Test
  public void corruptIntArraysTrailingComma() throws Exception {
    // Test a few cases of what happens if the R.txt is corrupted. It shouldn't happen unless there
    // is a bug in aapt, or R.txt is manually written the wrong way.
    Path path = createFile("R.txt", new String[] {"int[] styleable ActionMenuView { 1, }"});
    thrown.expectCause(NUMBER_FORMAT_EXCEPTION);
    ResourceSymbols.load(path, MoreExecutors.newDirectExecutorService()).get();
  }

  @Test
  public void corruptIntArraysOmittedMiddle() throws Exception {
    Path path = createFile("R.txt", "int[] styleable ActionMenuView { 1, , 2 }");
    thrown.expectCause(NUMBER_FORMAT_EXCEPTION);
    ResourceSymbols.load(path, MoreExecutors.newDirectExecutorService()).get();
  }

  @Test
  public void binaryDropsLibraryFields() throws Exception {
    boolean finalFields = true;
    // Test what happens if the binary R.txt is not a strict superset of the
    // library R.txt (overrides that drop elements).
    ResourceSymbols symbolValues =
        createSymbolFile("R.txt", "int layout stubbable_activity 0x7f020000");
    ResourceSymbols symbolsInLibrary =
        createSymbolFile(
            "lib.R.txt",
            "int id debug_text_field 0x1",
            "int id debug_text_field2 0x1",
            "int layout stubbable_activity 0x1");
    Path out = temp.resolve("classes");
    Files.createDirectories(out);
    RClassGenerator writer = RClassGenerator.with(out, symbolValues.asInitializers(), finalFields);
    writer.write("com.foo", symbolsInLibrary.asInitializers());

    Path packageDir = out.resolve("com/foo");
    checkFilesInPackage(packageDir, "R.class", "R$layout.class");
    Class<?> outerClass = checkTopLevelClass(out,
        "com.foo.R",
        "com.foo.R$layout");
    checkInnerClass(out,
        "com.foo.R$layout",
        outerClass,
        ImmutableMap.of("stubbable_activity", 0x7f020000),
        ImmutableMap.<String, List<Integer>>of(),
        finalFields
    );
  }
  
  @Test
  public void writeNothingWithNoResources() throws Exception {
    boolean finalFields = true;
    // Test what happens if the library R.txt has no elements.
    ResourceSymbols symbolValues =
        createSymbolFile("R.txt", "int layout stubbable_activity 0x7f020000");
    ResourceSymbols symbolsInLibrary = createSymbolFile("lib.R.txt");
    Path out = temp.resolve("classes");
    Files.createDirectories(out);
    RClassGenerator writer = RClassGenerator.with(out, symbolValues.asInitializers(), finalFields);
    writer.write("com.foo", symbolsInLibrary.asInitializers());

    Path packageDir = out.resolve("com/foo");
   
    checkFilesInPackage(packageDir);
  }

  @Test
  public void intArraysFinal() throws Exception {
    checkIntArrays(true);
  }

  @Test
  public void intArraysNonFinal() throws Exception {
    checkIntArrays(false);
  }

  public void checkIntArrays(boolean finalFields) throws Exception {
    ResourceSymbols symbolValues =
        createSymbolFile(
            "R.txt",
            "int attr android_layout 0x010100f2",
            "int attr bar 0x7f010001",
            "int attr baz 0x7f010002",
            "int attr fox 0x7f010003",
            "int attr attr 0x7f010004",
            "int attr another_attr 0x7f010005",
            "int attr zoo 0x7f010006",
            // Test several > 5 elements, clinit must use bytecodes other than iconst_0 to 5.
            "int[] styleable ActionButton { 0x010100f2, 0x7f010001, 0x7f010002, 0x7f010003, "
                + "0x7f010004, 0x7f010005, 0x7f010006 }",
            // The array indices of each attribute.
            "int styleable ActionButton_android_layout 0",
            "int styleable ActionButton_another_attr 5",
            "int styleable ActionButton_attr 4",
            "int styleable ActionButton_bar 1",
            "int styleable ActionButton_baz 2",
            "int styleable ActionButton_fox 3",
            "int styleable ActionButton_zoo 6");
    ResourceSymbols symbolsInLibrary = symbolValues;
    Path out = temp.resolve("classes");
    Files.createDirectories(out);
    RClassGenerator writer = RClassGenerator.with(out, symbolValues.asInitializers(), finalFields);
    writer.write("com.intArray", symbolsInLibrary.asInitializers());

    Path packageDir = out.resolve("com/intArray");
    checkFilesInPackage(packageDir, "R.class", "R$attr.class", "R$styleable.class");
    Class<?> outerClass = checkTopLevelClass(out,
        "com.intArray.R",
        "com.intArray.R$attr",
        "com.intArray.R$styleable");
    checkInnerClass(out,
        "com.intArray.R$attr",
        outerClass,
        ImmutableMap.<String, Integer>builder()
            .put("android_layout", 0x010100f2)
            .put("bar", 0x7f010001)
            .put("baz", 0x7f010002)
            .put("fox", 0x7f010003)
            .put("attr", 0x7f010004)
            .put("another_attr", 0x7f010005)
            .put("zoo", 0x7f010006)
            .build(),
        ImmutableMap.<String, List<Integer>>of(),
        finalFields
    );
    checkInnerClass(out,
        "com.intArray.R$styleable",
        outerClass,
        ImmutableMap.<String, Integer>builder()
            .put("ActionButton_android_layout", 0)
            .put("ActionButton_bar", 1)
            .put("ActionButton_baz", 2)
            .put("ActionButton_fox", 3)
            .put("ActionButton_attr", 4)
            .put("ActionButton_another_attr", 5)
            .put("ActionButton_zoo", 6)
            .build(),
        ImmutableMap.<String, List<Integer>>of(
            "ActionButton",
            ImmutableList.of(0x010100f2, 0x7f010001, 0x7f010002,
                0x7f010003, 0x7f010004, 0x7f010005, 0x7f010006)
        ),
        finalFields
    );
  }

  @Test
  public void emptyPackage() throws Exception {
    boolean finalFields = true;
    // Make sure we handle an empty package string.
    ResourceSymbols symbolValues = createSymbolFile("R.txt", "int string some_string 0x7f200000");
    ResourceSymbols symbolsInLibrary = symbolValues;
    Path out = temp.resolve("classes");
    Files.createDirectories(out);
    RClassGenerator writer = RClassGenerator.with(out, symbolValues.asInitializers(), finalFields);
    writer.write("", symbolsInLibrary.asInitializers());

    Path packageDir = out.resolve("");
    checkFilesInPackage(packageDir, "R.class", "R$string.class");
    Class<?> outerClass = checkTopLevelClass(out, "R", "R$string");
    checkInnerClass(
        out,
        "R$string",
        outerClass,
        ImmutableMap.of("some_string", 0x7f200000),
        ImmutableMap.<String, List<Integer>>of(),
        finalFields);
  }

  // Test utilities

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

  private ResourceSymbols createSymbolFile(String name, String... contents)
      throws IOException, InterruptedException, ExecutionException {
    Path path = createFile(name, contents);
    ListeningExecutorService executorService = MoreExecutors.newDirectExecutorService();
    ResourceSymbols symbolFile = ResourceSymbols.load(path, executorService).get();
    return symbolFile;
  }

  private static void checkFilesInPackage(Path packageDir, String... expectedFiles)
      throws IOException {
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(packageDir)) {
      ImmutableList<String> filesInPackage =
          ImmutableList.copyOf(
              Iterables.transform(
                  stream,
                  new Function<Path, String>() {
                    @Override
                    public String apply(Path path) {
                      return path.getFileName().toString();
                    }
                  }));
      assertThat(filesInPackage).containsExactly((Object[]) expectedFiles);
    }
  }

  private static Class<?> checkTopLevelClass(
      Path baseDir, String expectedClassName, String... expectedInnerClasses) throws Exception {
    try (URLClassLoader urlClassLoader = new URLClassLoader(new URL[] {baseDir.toUri().toURL()})) {
      Class<?> toplevelClass = urlClassLoader.loadClass(expectedClassName);
      assertThat(toplevelClass.getSuperclass()).isEqualTo(Object.class);
      int outerModifiers = toplevelClass.getModifiers();
      assertThat(Modifier.isFinal(outerModifiers)).isTrue();
      assertThat(Modifier.isPublic(outerModifiers)).isTrue();
      ImmutableList.Builder<String> actualClasses = ImmutableList.builder();
      for (Class<?> innerClass : toplevelClass.getClasses()) {
        assertThat(innerClass.getDeclaredClasses()).isEmpty();
        int modifiers = innerClass.getModifiers();
        assertThat(Modifier.isFinal(modifiers)).isTrue();
        assertThat(Modifier.isPublic(modifiers)).isTrue();
        assertThat(Modifier.isStatic(modifiers)).isTrue();
        actualClasses.add(innerClass.getName());
      }
      assertThat(actualClasses.build()).containsExactly((Object[]) expectedInnerClasses);
      return toplevelClass;
    }
  }

  private void checkInnerClass(
      Path baseDir,
      String expectedClassName,
      Class<?> outerClass,
      ImmutableMap<String, Integer> intFields,
      ImmutableMap<String, List<Integer>> intArrayFields,
      boolean areFieldsFinal)
      throws Exception {
    try (URLClassLoader urlClassLoader = new URLClassLoader(new URL[] {baseDir.toUri().toURL()})) {
      Class<?> innerClass = urlClassLoader.loadClass(expectedClassName);
      assertThat(innerClass.getSuperclass()).isEqualTo(Object.class);
      assertThat(innerClass.getEnclosingClass().toString()).isEqualTo(outerClass.toString());
      ImmutableMap.Builder<String, Integer> actualIntFields = ImmutableMap.builder();
      ImmutableMap.Builder<String, List<Integer>> actualIntArrayFields = ImmutableMap.builder();
      for (Field f : innerClass.getFields()) {
        int fieldModifiers = f.getModifiers();
        assertThat(Modifier.isFinal(fieldModifiers)).isEqualTo(areFieldsFinal);
        assertThat(Modifier.isPublic(fieldModifiers)).isTrue();
        assertThat(Modifier.isStatic(fieldModifiers)).isTrue();

        Class<?> fieldType = f.getType();
        if (fieldType.isPrimitive()) {
          assertThat(fieldType).isEqualTo(Integer.TYPE);
          actualIntFields.put(f.getName(), (Integer) f.get(null));
        } else {
          assertThat(fieldType.isArray()).isTrue();
          int[] asArray = (int[]) f.get(null);
          ImmutableList.Builder<Integer> list = ImmutableList.builder();
          for (int i : asArray) {
            list.add(i);
          }
          actualIntArrayFields.put(f.getName(), list.build());
        }
      }
      assertThat(actualIntFields.build()).containsExactlyEntriesIn(intFields);
      assertThat(actualIntArrayFields.build()).containsExactlyEntriesIn(intArrayFields);
    }
  }

}
