// Copyright 2017 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.lib.rules.android;

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

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.truth.BooleanSubject;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.rules.android.AndroidConfiguration.AndroidAaptVersion;
import com.google.devtools.build.lib.testutil.FakeAttributeMapper;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests {@link ResourceFilterFactory}. */
// TODO(asteinb): Test behavior not already covered in this test, and, when practical, move unit
// tests currently located in {@link AndroidBinaryTest} to this class instead.
@RunWith(JUnit4.class)
public class ResourceFilterFactoryTest extends ResourceTestBase {

  private NestedSet<ValidatedAndroidResources> getResources(ImmutableList<Artifact>... resources)
      throws Exception {
    NestedSetBuilder<ValidatedAndroidResources> builder = NestedSetBuilder.naiveLinkOrder();
    for (ImmutableList<Artifact> resourceList : resources) {
      builder.add(getResources(resourceList));
    }
    return builder.build();
  }

  private ValidatedAndroidResources getResources(ImmutableList<Artifact> resources)
      throws Exception {
    return makeValidatedResourcesFor(
        resources,
        /* includeAapt2Outs = */ true,
        new ProcessedAndroidManifest(getOutput("manifest"), "com.some.pkg", /* exported = */ false),
        ResourceDependencies.empty());
  }

  @Test
  public void testFilterInExecution() throws Exception {
    testNoopFilter(
        "en",
        "hdpi",
        /* filterInAnalysis = */ false,
        ImmutableList.of(
            "values-en/foo.xml", "values/foo.xml", "values-hdpi/foo.png", "values-ldpi/foo.png"));
  }

  @Test
  public void testFilterEmpty() throws Exception {
    testNoopFilter("", "", /* filterInAnalysis = */ true, ImmutableList.<String>of());
  }

  @Test
  public void testFilterDefaultAndNonDefault() throws Exception {
    testNoopFilter(
        "en",
        "xhdpi,xxhdpi",
        /* filterInAnalysis = */ true,
        ImmutableList.of("drawable/ic_clear.xml", "drawable-v21/ic_clear.xml"));
  }

  /**
   * Tests that version qualifiers are ignored for both resource qualifier and density filtering.
   */
  @Test
  public void testFilterVersionIgnored() throws Exception {
    testNoopFilter(
        "v4",
        "hdpi",
        /* filterInAnalysis = */ true,
        ImmutableList.of("drawable-hdpi-v4/foo.png", "drawable-hdpi-v11/foo.png"));
  }

  @Test
  public void testFilterByDensityPersistsOrdering() throws Exception {
    testFilter(
        "",
        "hdpi,ldpi",
        /* filterInAnalysis = */ true,
        // If we add resources to the output list in density order, these resources will be
        // rearranged.
        ImmutableList.of(
            "drawable-hdpi/foo.png",
            "drawable-ldpi/foo.png",
            "drawable-ldpi/bar.png",
            "drawable-hdpi/bar.png"),
        // Filter out some resources to make sure the original list isn't just returned because the
        // filtering was a no-op.
        ImmutableList.of("drawable-mdpi/foo.png", "drawable-mdpi/bar.png"));
  }

  /** Tests handling of Aapt's old region format */
  @Test
  public void testFilterOldLanguageFormat() throws Exception {
    testFilter(
        "en_US",
        "",
        /* filterInAnalysis = */ true,
        ImmutableList.of("values-en/foo.xml", "values-en-rUS/foo.xml"),
        ImmutableList.of("values-fr/foo.xml", "values-en-rCA/foo.xml"));

    errorConsumer.assertNoAttributeWarnings(
        ResourceFilterFactory.RESOURCE_CONFIGURATION_FILTERS_NAME);
  }

  @Test
  public void testFilterOldLanguageFormatWithAdditionalQualifiers() throws Exception {
    testFilter(
        "en_US-ldrtl",
        "",
        /* filterInAnalysis = */ true,
        ImmutableList.of("values-en/foo.xml", "values-en-rUS/foo.xml"),
        ImmutableList.of("values-fr/foo.xml", "values-en-rCA/foo.xml"));

    errorConsumer.assertNoAttributeWarnings(
        ResourceFilterFactory.RESOURCE_CONFIGURATION_FILTERS_NAME);
  }

  @Test
  public void testFilterOldLanguageFormatWithMcc() throws Exception {
    testFilter(
        "mcc111-en_US",
        "",
        /* filterInAnalysis = */ true,
        ImmutableList.of("values-en/foo.xml", "values-en-rUS/foo.xml"),
        ImmutableList.of("values-fr/foo.xml", "values-en-rCA/foo.xml"));

    errorConsumer.assertNoAttributeWarnings(
        ResourceFilterFactory.RESOURCE_CONFIGURATION_FILTERS_NAME);
  }

  @Test
  public void testFilterOldLanguageFormatWithMccAndMnc() throws Exception {
    testFilter(
        "mcc111-mnc111-en_US",
        "",
        /* filterInAnalysis = */ true,
        ImmutableList.of("values-en/foo.xml", "values-en-rUS/foo.xml"),
        ImmutableList.of("values-fr/foo.xml", "values-en-rCA/foo.xml"));

    errorConsumer.assertNoAttributeWarnings(
        ResourceFilterFactory.RESOURCE_CONFIGURATION_FILTERS_NAME);
  }

  @Test
  public void testFilterSerbianLatinCharacters() throws Exception {
    testFilter(
        "sr-Latn,sr-rLatn,sr_Latn,b+sr+Latn",
        "",
        /* filterInAnalysis = */ true,
        ImmutableList.of(
            "values-sr/foo.xml",
            "values-b+sr+Latn/foo.xml",
            "values-sr-Latn/foo.xml",
            "values-sr-rLatn/foo.xml"),
        // Serbian in explicitly Cyrillic characters should be filtered out.
        ImmutableList.of("values-b+sr+Cyrl/foo.xml"));

    errorConsumer.assertNoAttributeWarnings(
        ResourceFilterFactory.RESOURCE_CONFIGURATION_FILTERS_NAME);
  }

  @Test
  public void testFilterSerbianCharactersNotSpecified() throws Exception {
    testNoopFilter(
        "sr",
        "",
        /* filterInAnalysis = */ true,
        ImmutableList.of(
            "values-sr/foo.xml",
            "values-b+sr+Latn/foo.xml",
            "values-b+sr+Cyrl/foo.xml",
            "values-sr-Latn/foo.xml",
            "values-sr-rLatn/foo.xml"));

    errorConsumer.assertNoAttributeWarnings(
        ResourceFilterFactory.RESOURCE_CONFIGURATION_FILTERS_NAME);
  }

  @Test
  public void testFilterSpanishLatinAmericaAndCaribbean() throws Exception {
    testFilter(
        "es-419,es_419,b+es+419",
        "",
        /* filterInAnalysis = */ true,
        ImmutableList.of("values-es/foo.xml", "values-b+es+419/foo.xml", "values-es-419/foo.xml"),
        // Spanish with another region specified should be filtered out.
        ImmutableList.of("values-es-rUS/foo.xml"));

    errorConsumer.assertNoAttributeWarnings(
        ResourceFilterFactory.RESOURCE_CONFIGURATION_FILTERS_NAME);
  }

  @Test
  public void testFilterSpanishRegionNotSpecified() throws Exception {
    testNoopFilter(
        "es",
        "",
        /* filterInAnalysis = */ true,
        ImmutableList.of(
            "values-es/foo.xml",
            "values-b+es+419/foo.xml",
            "values-es-rUS/foo.xml",
            "values-es-419/foo.xml"));

    errorConsumer.assertNoAttributeWarnings(
        ResourceFilterFactory.RESOURCE_CONFIGURATION_FILTERS_NAME);
  }

  @Test
  public void testFilterDeprecatedQualifierFormatsRuleWarnings() throws RuleErrorException {
    ImmutableList<Artifact> badResources =
        getResources(
            "values-es_US/foo.xml",
            "drawable-sr-Latn/foo.xml",
            "layout-es-419/foo.xml",
            "values-mcc310-es_US/foo.xml",
            "values-sr_rLatn/foo.xml",
            "drawable-es_419/foo.xml");

    ImmutableList<String> expectedWarnings =
        ImmutableList.of(
            "For resource folder drawable-sr-Latn, when referring to Serbian in Latin characters, "
                + "use of qualifier 'sr-Latn' is deprecated. Use 'b+sr+Latn' instead.",
            "For resource folder layout-es-419, when referring to Spanish for Latin America and "
                + "the Caribbean, use of qualifier 'es-419' is deprecated. Use 'b+es+419' instead.",
            "For resource folder values-es_US, when referring to locale qualifiers with regions, "
                + "use of qualifier 'es_US' is deprecated. Use 'es-rUS' instead.");

    ResourceFilterFactory filter =
        new ResourceFilterFactory(
            ImmutableList.of("en"), ImmutableList.of(), /* filterInAnalysis = */ true);

    doFilter(filter, badResources);
    assertThat(errorConsumer.getAndClearRuleWarnings()).containsExactlyElementsIn(expectedWarnings);
    errorConsumer.assertNoAttributeWarnings(
        ResourceFilterFactory.RESOURCE_CONFIGURATION_FILTERS_NAME);

    // Filtering again with this filter should not produce additional warnings
    doFilter(filter, badResources);
    errorConsumer.assertNoRuleWarnings();
    errorConsumer.assertNoAttributeWarnings(
        ResourceFilterFactory.RESOURCE_CONFIGURATION_FILTERS_NAME);

    // Filtering with a new filter should produce warnings again, since it is working on a different
    // target
    filter =
        new ResourceFilterFactory(
            ImmutableList.of("en"), ImmutableList.of(), /* filterInAnalysis = */ true);
    doFilter(filter, badResources);
    assertThat(errorConsumer.getAndClearRuleWarnings()).containsExactlyElementsIn(expectedWarnings);
    errorConsumer.assertNoAttributeWarnings(
        ResourceFilterFactory.RESOURCE_CONFIGURATION_FILTERS_NAME);
  }

  @Test
  public void testFilterResourceConflict() throws Exception {
    testNoopFilter(
        "en",
        "hdpi",
        /* filterInAnalysis = */ true,
        ImmutableList.of(
            "first-subdir/res/drawable-en-hdpi/foo.png",
            "second-subdir/res/drawable-en-hdpi/foo.png"));
  }

  private void testNoopFilter(
      String resourceConfigurationFilters,
      String densities,
      boolean filterInAnalysis,
      List<String> resources)
      throws Exception {
    testFilter(
        resourceConfigurationFilters,
        densities,
        filterInAnalysis,
        resources,
        ImmutableList.<String>of());
  }

  private void testFilter(
      String resourceConfigurationFilters,
      String densities,
      boolean filterInAnalysis,
      List<String> resourcesToKeep,
      List<String> resourcesToDiscard)
      throws Exception {
    List<Artifact> unexpectedResources = new ArrayList<>();
    for (String resource : resourcesToDiscard) {
      unexpectedResources.add(getResource(resource));
    }

    List<Artifact> expectedResources = new ArrayList<>();
    for (String resource : resourcesToKeep) {
      expectedResources.add(getResource(resource));
    }

    ImmutableList<Artifact> allArtifacts =
        ImmutableList.copyOf(Iterables.concat(expectedResources, unexpectedResources));
    ResourceFilterFactory resourceFilterFactory =
        makeResourceFilter(resourceConfigurationFilters, densities, filterInAnalysis);
    ImmutableList<Artifact> filtered = doFilter(resourceFilterFactory, allArtifacts);

    assertThat(filtered).containsExactlyElementsIn(expectedResources).inOrder();

    // Only dependencies need to be tracked for ignoring in execution
    assertThat(resourceFilterFactory.getResourcesToIgnoreInExecution()).isEmpty();
  }

  @Test
  public void testFilterLocalAndTransitive() throws Exception {
    Artifact localResourceToKeep = getResource("drawable-en-hdpi/local.png");
    Artifact localResourceToDiscard = getResource("drawable-en-ldpi/local.png");

    // These resources go in different ResourceContainers to ensure we are filter across all
    // resources.
    Artifact directResourceToKeep = getResource("direct/drawable-en-hdpi/direct.png");
    Artifact directResourceToDiscard = getResource("direct/drawable-en-ldpi/direct.png");
    Artifact transitiveResourceToKeep = getResource("transitive/drawable-en-hdpi/transitive.png");
    Artifact transitiveResourceToDiscard =
        getResource("transitive/drawable-en-ldpi/transitive.png");

    AndroidResources localResources =
        AndroidResources.forResources(
            errorConsumer,
            ImmutableList.of(localResourceToKeep, localResourceToDiscard),
            "resource_files");

    ResourceDependencies resourceDependencies =
        ResourceDependencies.empty()
            .withResources(
                getResources(
                    ImmutableList.of(transitiveResourceToDiscard),
                    ImmutableList.of(transitiveResourceToKeep)),
                getResources(
                    ImmutableList.of(directResourceToDiscard),
                    ImmutableList.of(directResourceToKeep)),
                new NestedSetBuilder<Artifact>(Order.NAIVE_LINK_ORDER)
                    .add(directResourceToDiscard)
                    .add(directResourceToKeep)
                    .addTransitive(
                        NestedSetBuilder.create(
                            Order.NAIVE_LINK_ORDER,
                            transitiveResourceToDiscard,
                            transitiveResourceToKeep))
                    .build());

    ResourceFilterFactory resourceFilterFactory =
        makeResourceFilter("en", "hdpi", /* filterInAnalysis = */ true);
    ResourceFilter filter =
        resourceFilterFactory.getResourceFilter(
            errorConsumer, resourceDependencies, localResources);

    assertThat(localResources.filterLocalResources(errorConsumer, filter).getResources())
        .containsExactly(localResourceToKeep);

    ResourceDependencies filteredResourceDeps = resourceDependencies.filter(errorConsumer, filter);

    // TODO: Remove - assert was same order before
    assertThat(resourceDependencies.getTransitiveResources())
        .containsAllOf(directResourceToKeep, transitiveResourceToKeep)
        .inOrder();

    assertThat(filteredResourceDeps.getTransitiveResources())
        .containsExactly(directResourceToKeep, transitiveResourceToKeep)
        .inOrder();

    List<ValidatedAndroidResources> directContainers =
        filteredResourceDeps.getDirectResourceContainers().toList();
    assertThat(directContainers).hasSize(2);

    ValidatedAndroidResources directToDiscard = directContainers.get(0);
    assertThat(directToDiscard.getResources()).isEmpty();
    assertThat(directToDiscard.getResourceRoots()).isEmpty();

    ValidatedAndroidResources directToKeep = directContainers.get(1);
    assertThat(directToKeep.getResources()).containsExactly(directResourceToKeep);
    assertThat(directToKeep.getResourceRoots())
        .containsExactly(
            directResourceToKeep.getExecPath().getParentDirectory().getParentDirectory());

    List<ValidatedAndroidResources> transitiveContainers =
        filteredResourceDeps.getTransitiveResourceContainers().toList();
    assertThat(transitiveContainers).hasSize(2);

    ValidatedAndroidResources transitiveToDiscard = transitiveContainers.get(0);
    assertThat(transitiveToDiscard.getResources()).isEmpty();
    assertThat(transitiveToDiscard.getResourceRoots()).isEmpty();

    ValidatedAndroidResources transitiveToKeep = transitiveContainers.get(1);
    assertThat(transitiveToKeep.getResources()).containsExactly(transitiveResourceToKeep);
    assertThat(transitiveToKeep.getResourceRoots())
        .containsExactly(
            transitiveResourceToKeep.getExecPath().getParentDirectory().getParentDirectory());

    // We tell the resource processing actions to ignore references to filtered resources from
    // dependencies.
    assertThat(resourceFilterFactory.getResourcesToIgnoreInExecution())
        .containsExactly("drawable-en-ldpi/direct.png", "drawable-en-ldpi/transitive.png");
  }

  @Test
  public void testIsPrefilteringFilterInExecution() throws Exception {
    assertIsPrefiltering(/* filterInAnalysis = */ false, false);
  }

  @Test
  public void testIsPrefilteringFilterInAnalysis() throws Exception {
    assertIsPrefiltering(/* filterInAnalysis = */ true, true);
  }

  private void assertIsPrefiltering(boolean filterInAnalysis, boolean expectWhenNonEmpty)
      throws Exception {
    // Empty filters should never prefilter
    assertIsPrefiltering(false, false, filterInAnalysis).isFalse();

    // Prefiltering behavior should be the same regardless of which setting is set
    assertIsPrefiltering(true, false, filterInAnalysis).isEqualTo(expectWhenNonEmpty);
    assertIsPrefiltering(false, true, filterInAnalysis).isEqualTo(expectWhenNonEmpty);
    assertIsPrefiltering(true, true, filterInAnalysis).isEqualTo(expectWhenNonEmpty);
  }

  private BooleanSubject assertIsPrefiltering(
      boolean hasConfigurationFilters, boolean hasDensities, boolean filterInAnalysis)
      throws Exception {
    return assertThat(
        makeResourceFilter(
                hasConfigurationFilters ? "en" : "", hasDensities ? "hdpi" : "", filterInAnalysis)
            .isPrefiltering());
  }

  private ResourceFilterFactory makeResourceFilter(
      String resourceConfigurationFilters, String densities, boolean filterInAnalysis) {
    return makeResourceFilter(
        resourceConfigurationFilters.isEmpty()
            ? ImmutableList.of()
            : ImmutableList.of(resourceConfigurationFilters),
        densities.isEmpty() ? ImmutableList.of() : ImmutableList.of(densities),
        filterInAnalysis);
  }

  private ResourceFilterFactory makeResourceFilter(
      ImmutableList<String> resourceConfigurationFilters,
      ImmutableList<String> densities,
      boolean filterInAnalysis) {

    return ResourceFilterFactory.fromAttrs(
        filterInAnalysis ? AndroidAaptVersion.AAPT : AndroidAaptVersion.AAPT2,
        getAttributeMap(resourceConfigurationFilters, densities));
  }

  private AttributeMap getAttributeMap(
      ImmutableList<String> resourceConfigurationFilters, ImmutableList<String> densities) {
    return FakeAttributeMapper.builder()
        .withStringList(
            ResourceFilterFactory.RESOURCE_CONFIGURATION_FILTERS_NAME, resourceConfigurationFilters)
        .withStringList(ResourceFilterFactory.DENSITIES_NAME, densities)
        .build();
  }

  private ImmutableList<Artifact> doFilter(
      ResourceFilterFactory resourceFilterFactory, ImmutableList<Artifact> artifacts)
      throws RuleErrorException {
    AndroidResources localResources =
        AndroidResources.forResources(errorConsumer, artifacts, "resource_files");

    ResourceDependencies resourceDeps = ResourceDependencies.empty();

    ResourceFilter filter =
        resourceFilterFactory.getResourceFilter(errorConsumer, resourceDeps, localResources);

    assertThat(resourceDeps.filter(errorConsumer, filter)).isSameAs(resourceDeps);

    return localResources.filterLocalResources(errorConsumer, filter).getResources();
  }
}
