/*
 * Copyright 2014-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.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;

import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.rules.Sha1HashCode;
import com.facebook.buck.testutil.integration.BuckBuildLog;
import com.facebook.buck.testutil.integration.DebuggableTemporaryFolder;
import com.facebook.buck.testutil.integration.ProjectWorkspace;
import com.facebook.buck.testutil.integration.TestDataHelper;
import com.facebook.buck.testutil.integration.ZipInspector;
import com.facebook.buck.util.DefaultPropertyFinder;
import com.facebook.buck.util.ProcessExecutor;
import com.facebook.buck.util.VersionStringComparator;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.regex.Pattern;

public class AndroidResourceFilterIntegrationTest {

  private static boolean isBuildToolsNew;
  private static Path pathToAapt;

  private static final String APK_PATH_FORMAT = "buck-out/gen/apps/sample/%s.apk";

  @Rule
  public DebuggableTemporaryFolder tmpFolder = new DebuggableTemporaryFolder();

  private ProjectWorkspace workspace;

  @BeforeClass
  public static void findBuildToolsVersion() {
    AssumeAndroidPlatform.assumeSdkIsAvailable();
    ProjectFilesystem filesystem = new ProjectFilesystem(Paths.get("."));
    AndroidDirectoryResolver resolver = new DefaultAndroidDirectoryResolver(
        filesystem,
        Optional.<String>absent(),
        new DefaultPropertyFinder(filesystem, ImmutableMap.copyOf(System.getenv())));
    pathToAapt = AndroidPlatformTarget.getDefaultPlatformTarget(
        resolver,
        Optional.<Path>absent()).getAaptExecutable();
    String buildToolsVersion = pathToAapt.getParent().getFileName().toString();
    isBuildToolsNew = new VersionStringComparator().compare(buildToolsVersion, "21") >= 0;
  }

  @Before
  public void setUp() throws IOException {
    workspace = TestDataHelper.createProjectWorkspaceForScenario(
        this, "android_project", tmpFolder);
    workspace.setUp();
  }

  @Test
  public void testApkWithoutResourceFilter() throws IOException {
    ProjectWorkspace.ProcessResult result = workspace.runBuckCommand("build", "//apps/sample:app");
    result.assertSuccess();

    File apkFile = workspace.getFile(String.format(APK_PATH_FORMAT, "app"));
    ZipInspector zipInspector = new ZipInspector(apkFile);

    if (isBuildToolsNew) {
      zipInspector.assertFileExists("res/drawable-mdpi-v4/app_icon.png");
      zipInspector.assertFileExists("res/drawable-hdpi-v4/app_icon.png");
      zipInspector.assertFileExists("res/drawable-xhdpi-v4/app_icon.png");
    } else {
      zipInspector.assertFileExists("res/drawable-mdpi/app_icon.png");
      zipInspector.assertFileExists("res/drawable-hdpi/app_icon.png");
      zipInspector.assertFileExists("res/drawable-xhdpi/app_icon.png");
    }
  }

  @Test
  public void testApkWithMdpiFilter() throws IOException {
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", "//apps/sample:app_mdpi");
    result.assertSuccess();

    File apkFile = workspace.getFile(String.format(APK_PATH_FORMAT, "app_mdpi"));
    ZipInspector zipInspector = new ZipInspector(apkFile);

    if (isBuildToolsNew) {
      zipInspector.assertFileExists("res/drawable-mdpi-v4/app_icon.png");
      zipInspector.assertFileDoesNotExist("res/drawable-hdpi-v4/app_icon.png");
      zipInspector.assertFileDoesNotExist("res/drawable-xhdpi-v4/app_icon.png");
    } else {
      zipInspector.assertFileExists("res/drawable-mdpi/app_icon.png");
      zipInspector.assertFileDoesNotExist("res/drawable-hdpi/app_icon.png");
      zipInspector.assertFileDoesNotExist("res/drawable-xhdpi/app_icon.png");
    }
  }

  @Test
  public void testModifyingImageRebuildsResourcesFilter() throws IOException {
    ProjectWorkspace.ProcessResult result = workspace.runBuckBuild("//apps/sample:app_mdpi");
    result.assertSuccess();

    File apkFile = workspace.getFile(String.format(APK_PATH_FORMAT, "app_mdpi"));
    String iconPath = isBuildToolsNew
        ? "res/drawable-mdpi-v4/app_icon.png"
        : "res/drawable-mdpi/app_icon.png";
    long firstImageCrc = new ZipInspector(apkFile).getCrc(iconPath);

    workspace.copyFile(
        "res/com/sample/base/res/drawable-hdpi/app_icon.png",
        "res/com/sample/base/res/drawable-mdpi/app_icon.png");

    workspace.resetBuildLogFile();
    result = workspace.runBuckBuild("//apps/sample:app_mdpi");
    result.assertSuccess();

    BuckBuildLog buildLog = workspace.getBuildLog();
    buildLog.assertTargetBuiltLocally("//apps/sample:app_mdpi");

    apkFile = workspace.getFile(String.format(APK_PATH_FORMAT, "app_mdpi"));
    long secondImageCrc = new ZipInspector(apkFile).getCrc(iconPath);

    assertNotEquals(firstImageCrc, secondImageCrc);
  }

  @Test
  public void testApkWithXhdpiAndHdpiFilter() throws IOException {
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", "//apps/sample:app_hdpi_xhdpi");
    result.assertSuccess();

    File apkFile = workspace.getFile(String.format(APK_PATH_FORMAT, "app_hdpi_xhdpi"));
    ZipInspector zipInspector = new ZipInspector(apkFile);

    if (isBuildToolsNew) {
      zipInspector.assertFileDoesNotExist("res/drawable-mdpi-v4/app_icon.png");
      zipInspector.assertFileExists("res/drawable-hdpi-v4/app_icon.png");
      zipInspector.assertFileExists("res/drawable-xhdpi-v4/app_icon.png");
    } else {
      zipInspector.assertFileDoesNotExist("res/drawable-mdpi/app_icon.png");
      zipInspector.assertFileExists("res/drawable-hdpi/app_icon.png");
      zipInspector.assertFileExists("res/drawable-xhdpi/app_icon.png");
    }
  }

  @Test
  public void testApkWithStringsAsAssets() throws IOException {
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", "//apps/sample:app_comp_str");
    result.assertSuccess();

    File apkFile = workspace.getFile(String.format(APK_PATH_FORMAT, "app_comp_str"));
    ZipInspector zipInspector = new ZipInspector(apkFile);

    zipInspector.assertFileExists("assets/strings/fr.fbstr");
  }

  @Test
  public void testStringArtifactsAreCached() throws IOException {
    workspace.enableDirCache();
    workspace.runBuckBuild("//apps/sample:app_comp_str").assertSuccess();
    BuckBuildLog buildLog = workspace.getBuildLog();
    Sha1HashCode androidBinaryRuleKey = buildLog.getRuleKey("//apps/sample:app_comp_str");
    File cachedFile = workspace.getFile("buck-cache/" + androidBinaryRuleKey.getHash());
    assertTrue(cachedFile.delete());

    workspace.runBuckCommand("clean").assertSuccess();
    workspace.runBuckBuild("//apps/sample:app_comp_str").assertSuccess();
  }

  @Test
  public void testApkWithStringsAsAssetsAndResourceFilter() throws IOException {
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckBuild("//apps/sample:app_comp_str_xhdpi");
    result.assertSuccess();

    File apkFile = workspace.getFile(String.format(APK_PATH_FORMAT, "app_comp_str_xhdpi"));
    ZipInspector zipInspector = new ZipInspector(apkFile);

    zipInspector.assertFileExists("assets/strings/fr.fbstr");

    if (isBuildToolsNew) {
      zipInspector.assertFileExists("res/drawable-xhdpi-v4/app_icon.png");
      zipInspector.assertFileDoesNotExist("res/drawable-hdpi-v4/app_icon.png");
      zipInspector.assertFileDoesNotExist("res/drawable-mdpi-v4/app_icon.png");
    } else {
      zipInspector.assertFileExists("res/drawable-xhdpi/app_icon.png");
      zipInspector.assertFileDoesNotExist("res/drawable-hdpi/app_icon.png");
      zipInspector.assertFileDoesNotExist("res/drawable-mdpi/app_icon.png");
    }
  }

  @Test
  public void testAsset() throws IOException {
    workspace.enableDirCache();
    workspace.runBuckBuild("//apps/sample:app").assertSuccess();
    String apkFilePath = String.format(APK_PATH_FORMAT, "app");

    File apkFile = workspace.getFile(apkFilePath);
    ZipInspector zipInspector = new ZipInspector(apkFile);

    long firstCrc = zipInspector.getCrc("assets/asset_file.txt");

    workspace.replaceFileContents(
        "res/com/sample/asset_only/assets/asset_file.txt",
        "Hello",
        "Bye");
    workspace.runBuckBuild("//apps/sample:app").assertSuccess();

    apkFile = workspace.getFile(apkFilePath);
    zipInspector = new ZipInspector(apkFile);

    long secondCrc = zipInspector.getCrc("assets/asset_file.txt");

    assertNotEquals("Rebuilt APK file must include the new asset file.", firstCrc, secondCrc);
  }

  @Test
  public void testEnglishBuildDoesntContainFrenchStrings()
      throws IOException, InterruptedException {
    workspace.runBuckBuild("//apps/sample:app").assertSuccess();
    String apkFilePath = String.format(APK_PATH_FORMAT, "app");
    File apkFile = workspace.getFile(apkFilePath);

    int matchingLines = runAaptDumpResources(apkFile);
    assertEquals(2, matchingLines);

    workspace.runBuckBuild("//apps/sample:app_en").assertSuccess();
    apkFilePath = String.format(APK_PATH_FORMAT, "app_en");
    apkFile = workspace.getFile(apkFilePath);

    matchingLines = runAaptDumpResources(apkFile);
    assertEquals(1, matchingLines);
  }

  private int runAaptDumpResources(File apkFile) throws IOException, InterruptedException {
    final Pattern pattern = Pattern.compile(".*com.example:string/base_button: t=.*");
    ProcessExecutor.Result result = workspace.runCommand(
        pathToAapt.toAbsolutePath().toString(),
        "dump",
        "resources",
        apkFile.getAbsolutePath());
    assertEquals(0, result.getExitCode());
    return FluentIterable.from(
        Splitter.on('\n').split(result.getStdout().or(""))).filter(
        new Predicate<String>() {
          @Override
          public boolean apply(String input) {
            return pattern.matcher(input).matches();
          }
        }).size();
  }
}
