/*
 * Copyright 2013-present Facebook, Inc.
 *
 * 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.facebook.buck.android;

import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;

import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.util.ProjectFilesystem;
import com.facebook.buck.util.XmlDomParser;
import com.google.common.base.Splitter;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.io.Files;

import org.easymock.EasyMockSupport;
import org.junit.Test;
import org.w3c.dom.NodeList;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;

public class CompileStringsStepTest extends EasyMockSupport {

  private static final String XML_HEADER = "<?xml version='1.0' encoding='utf-8'?>";

  private static final String TESTDATA_DIR = "testdata/com/facebook/buck/android/";
  private static final String FIRST_FILE = TESTDATA_DIR + "first/res/values-es/strings.xml";
  private static final String SECOND_FILE = TESTDATA_DIR + "second/res/values-es/strings.xml";
  private static final String THIRD_FILE = TESTDATA_DIR + "third/res/values-pt/strings.xml";
  private static final String FOURTH_FILE = TESTDATA_DIR + "third/res/values-pt-rBR/strings.xml";

  @Test
  public void testStringFilePattern() {
    testStringPathRegex("res/values-es/strings.xml", true, "es", null);
    testStringPathRegex("/one/res/values-es/strings.xml", true, "es", null);
    testStringPathRegex("/two/res/values-es-rUS/strings.xml", true, "es", "US");
    // Not matching strings.
    testStringPathRegex("/one/res/values/strings.xml", false, null, null);
    testStringPathRegex("/one/res/values-/strings.xml", false, null, null);
    testStringPathRegex("/one/res/values-e/strings.xml", false, null, null);
    testStringPathRegex("/one/res/values-esc/strings.xml", false, null, null);
    testStringPathRegex("/one/res/values-es-rU/strings.xml", false, null, null);
    testStringPathRegex("/one/res/values-es-rUSA/strings.xml", false, null, null);
    testStringPathRegex("/one/res/values-es-RUS/strings.xml", false, null, null);
    testStringPathRegex("/one/res/values-rUS/strings.xml", false, null, null);
  }

  private void testStringPathRegex(String input, boolean matches, String locale, String country) {
    Matcher matcher = CompileStringsStep.STRING_FILE_PATTERN.matcher(input);
    assertEquals(matches, matcher.matches());
    if (!matches) {
      return;
    }
    assertEquals(locale, matcher.group(1));
    assertEquals(country, matcher.group(2));
  }

  @Test
  public void testRDotTxtContentsPattern() {
    testContentRegex("  int string r_name 0xdeadbeef", false, null, null, null);
    testContentRegex("int string r_name 0xdeadbeef  ", false, null, null, null);
    testContentRegex("int string r_name 0xdeadbeef", true, "string", "r_name", "deadbeef");
    testContentRegex("int string r_name 0x", false, null, null, null);
    testContentRegex("int array r_name 0xdead", true, "array", "r_name", "dead");
    testContentRegex("int plurals r_name 0xdead", true, "plurals", "r_name", "dead");
    testContentRegex("int plural r_name 0xdead", false, null, null, null);
    testContentRegex("int plurals r name 0xdead", false, null, null, null);
    testContentRegex("int[] string r_name 0xdead", false, null, null, null);
  }

  private void testContentRegex(
      String input,
      boolean matches,
      String resourceType,
      String resourceName,
      String resourceId) {

    Matcher matcher = CompileStringsStep.R_DOT_TXT_STRING_RESOURCE_PATTERN.matcher(input);
    assertEquals(matches, matcher.matches());
    if (!matches) {
      return;
    }
    assertEquals("Resource type does not match.", resourceType, matcher.group(1));
    assertEquals("Resource name does not match.", resourceName, matcher.group(2));
    assertEquals("Resource id does not match.", resourceId, matcher.group(3));
  }

  @Test
  public void testGroupFilesByLocale() {
    ImmutableSet<String> files = ImmutableSet.of(
        "/project/dir/res/values-da/strings.xml",
        "/project/dir/res/values-da-rAB/strings.xml",
        "/project/dir/dontmatch/res/values/strings.xml",
        "/project/groupme/res/values-da/strings.xml",
        "/project/groupmetoo/res/values-da-rAB/strings.xml",
        "/project/foreveralone/res/values-es/strings.xml"
    );

    ImmutableMultimap<String, String> groupedByLocale =
        createNonExecutingStep().groupFilesByLocale(files);

    ImmutableMultimap<String, String> expectedMap =
        ImmutableMultimap.<String, String>builder()
          .putAll("da", ImmutableSet.<String>of(
              "/project/dir/res/values-da/strings.xml",
              "/project/groupme/res/values-da/strings.xml"))
          .putAll("da_AB", ImmutableSet.<String>of(
              "/project/dir/res/values-da-rAB/strings.xml",
              "/project/groupmetoo/res/values-da-rAB/strings.xml"))
          .putAll("es", ImmutableSet.<String>of("/project/foreveralone/res/values-es/strings.xml"))
          .build();

    assertEquals("Incorrect grouping of files by locale.", expectedMap, groupedByLocale);
  }

  @Test
  public void testScrapeStringNodes() throws IOException {
    String xmlInput =
          "<string name='name1'>Value1</string>" +
          "<string name='name2'>Value with space</string>" +
          "<string name='name3'>Value with \"quotes\"</string>" +
          "<string name='name4'></string>" +
          "<string name='name3'>IGNORE</string>" + // ignored because "name3" already found
          "<string name='name5'>Value with %1$s</string>";
    NodeList stringNodes = XmlDomParser.parse(createResourcesXml(xmlInput))
        .getElementsByTagName("string");

    Map<Integer, String> stringsMap = Maps.newHashMap();
    CompileStringsStep step = createNonExecutingStep();
    step.addResourceNameToIdMap(ImmutableMap.of(
        "name1", 1,
        "name2", 2,
        "name3", 3,
        "name4", 4,
        "name5", 5));
    step.scrapeStringNodes(stringNodes, stringsMap);

    assertEquals(
        "Incorrect map of resource id to string values.",
        ImmutableMap.of(
            1, "Value1",
            2, "Value with space",
            3, "Value with \"quotes\"",
            4, "",
            5, "Value with %1$s"),
        stringsMap
    );
  }

  @Test
  public void testScrapePluralsNodes() throws IOException {
    String xmlInput =
          "<plurals name='name1'>" +
            "<item quantity='zero'>%d people saw this</item>" +
            "<item quantity='one'>%d person saw this</item>" +
            "<item quantity='many'>%d people saw this</item>" +
          "</plurals>" +
          "<plurals name='name2'>" +
            "<item quantity='zero'>%d people ate this</item>" +
            "<item quantity='many'>%d people ate this</item>" +
          "</plurals>" +
          "<plurals name='name3'></plurals>" + // Test empty array.
          "<plurals name='name2'></plurals>"; // Ignored since "name2" already found.
    NodeList pluralsNodes = XmlDomParser.parse(createResourcesXml(xmlInput))
        .getElementsByTagName("plurals");

    Map<Integer, ImmutableMap<String, String>> pluralsMap = Maps.newHashMap();
    CompileStringsStep step = createNonExecutingStep();
    step.addResourceNameToIdMap(ImmutableMap.of(
        "name1", 1,
        "name2", 2,
        "name3", 3));
    step.scrapePluralsNodes(pluralsNodes, pluralsMap);

    assertEquals(
        "Incorrect map of resource id to plural values.",
        ImmutableMap.of(
            1, ImmutableMap.of(
                "zero", "%d people saw this",
                "one", "%d person saw this",
                "many", "%d people saw this"),
            2, ImmutableMap.of(
                "zero", "%d people ate this",
                "many", "%d people ate this"),
            3, ImmutableMap.of()
        ),
        pluralsMap
    );
  }

  @Test
  public void testScrapeStringArrayNodes() throws IOException {
    String xmlInput =
          "<string-array name='name1'>" +
            "<item>Value11</item>" +
            "<item>Value12</item>" +
          "</string-array>" +
          "<string-array name='name2'>" +
            "<item>Value21</item>" +
          "</string-array>" +
          "<string-array name='name3'></string-array>" +
          "<string-array name='name2'>" +
            "<item>ignored</item>" + // Ignored because "name2" already found above.
          "</string-array>";

    NodeList arrayNodes = XmlDomParser.parse(createResourcesXml(xmlInput))
        .getElementsByTagName("string-array");

    Multimap<Integer, String> arraysMap = ArrayListMultimap.create();
    CompileStringsStep step = createNonExecutingStep();
    step.addResourceNameToIdMap(ImmutableMap.of(
        "name1", 1,
        "name2", 2,
        "name3", 3));
    step.scrapeStringArrayNodes(arrayNodes, arraysMap);

    assertEquals(
        "Incorrect map of resource id to string arrays.",
        ImmutableMultimap.builder()
            .put(1, "Value11")
            .put(1, "Value12")
            .put(2, "Value21")
            .build(),
        arraysMap
    );
  }

  private CompileStringsStep createNonExecutingStep() {
    return new CompileStringsStep(
        createMock(FilterResourcesStep.class),
        createMock(Path.class),
        createMock(Path.class));
  }

  private String createResourcesXml(String contents) {
    return XML_HEADER + "<resources>" + contents + "</resources>";
  }

  @Test
  public void testSuccessfulStepExecution() throws IOException {
    Path destinationDir = Paths.get("");
    Path rDotJavaSrcDir = Paths.get("");

    ExecutionContext context = createMock(ExecutionContext.class);
    FakeProjectFileSystem fileSystem = new FakeProjectFileSystem();
    expect(context.getProjectFilesystem()).andStubReturn(fileSystem);

    FilterResourcesStep filterResourcesStep = createMock(FilterResourcesStep.class);
    expect(filterResourcesStep.getNonEnglishStringFiles()).andReturn(ImmutableSet.of(
        FIRST_FILE,
        SECOND_FILE,
        THIRD_FILE,
        FOURTH_FILE));

    replayAll();
    CompileStringsStep step = new CompileStringsStep(
        filterResourcesStep,
        rDotJavaSrcDir,
        destinationDir);
    assertEquals(0, step.execute(context));
    Map<String, byte[]> fileContentsMap = fileSystem.getFileContents();
    assertEquals("Incorrect number of string files written.", 3, fileContentsMap.size());
    for (Map.Entry<String, byte[]> entry : fileContentsMap.entrySet()) {
      File expectedFile = Paths.get(TESTDATA_DIR + entry.getKey()).toFile();
      assertArrayEquals(createBinaryStream(expectedFile), fileContentsMap.get(entry.getKey()));
    }

    verifyAll();
  }

  private byte[] createBinaryStream(File expectedFile) throws IOException {
    try (
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      DataOutputStream stream = new DataOutputStream(bos)
    ) {
      for (String line : Files.readLines(expectedFile, Charset.defaultCharset())) {
        for (String token : Splitter.on('|').split(line)) {
          char dataType = token.charAt(0);
          String value = token.substring(2);
          switch (dataType) {
            case 'i':
              stream.writeInt(Integer.parseInt(value));
              break;
            case 's':
              stream.writeShort(Integer.parseInt(value));
              break;
            case 'b':
              stream.writeByte(Integer.parseInt(value));
              break;
            case 't':
              stream.write(value.getBytes());
              break;
            default:
              throw new RuntimeException("Unexpected data type in .fbstr file: " + dataType);
          }
        }
      }

      return bos.toByteArray();
    }
  }


  private static class FakeProjectFileSystem extends ProjectFilesystem {

    private ImmutableMap.Builder<String, byte[]> fileContentsMapBuilder = ImmutableMap.builder();

    public FakeProjectFileSystem() {
      super(new File("."));
    }

    @Override
    public File getFileForRelativePath(Path path) {
      return path.toFile();
    }

    @Override
    public List<String> readLines(Path path) throws IOException {
      Path fullPath = Paths.get(TESTDATA_DIR).resolve(path);
      return Files.readLines(fullPath.toFile(), Charset.defaultCharset());
    }

    @Override
    public void writeBytesToPath(byte[] content, Path path) {
      fileContentsMapBuilder.put(path.getFileName().toString(), content);
    }

    public Map<String, byte[]> getFileContents() {
      return fileContentsMapBuilder.build();
    }
  }
}
