// Copyright 2015 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.skyframe;

import com.google.common.base.Predicate;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.cmdline.ResolvedTargets;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.BuildFileNotFoundException;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.packages.TestTargetUtils;
import com.google.devtools.build.lib.skyframe.TestsInSuiteValue.TestsInSuiteKey;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.build.skyframe.ValueOrException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * TestsInSuiteFunction takes a single test_suite target and expands all of the tests it contains,
 * possibly recursively.
 */
// TODO(ulfjack): What about test_suite rules that include each other.
final class TestsInSuiteFunction implements SkyFunction {
  @Override
  public SkyValue compute(SkyKey key, Environment env) throws InterruptedException {
    TestsInSuiteKey expansion = (TestsInSuiteKey) key.argument();
    ResolvedTargets<Target> result =
        computeTestsInSuite(env, expansion.getTestSuite(), expansion.isStrict());
    if (env.valuesMissing()) {
      return null;
    }
    return new TestsInSuiteValue(result);
  }

  /**
   * Populates 'result' with all the tests associated with the specified 'testSuite'. Throws an
   * exception if any target is missing.
   *
   * <p>CAUTION! Keep this logic consistent with {@code TestSuite}!
   */
  private static ResolvedTargets<Target> computeTestsInSuite(
      Environment env, Rule testSuite, boolean strict) throws InterruptedException {
    ResolvedTargets.Builder<Target> builder = ResolvedTargets.builder();
    List<Target> testsAndSuites = new ArrayList<>();
    // Note that testsAndSuites can contain input file targets; the test_suite rule does not
    // restrict the set of targets that can appear in tests or suites.
    builder.mergeError(getPrerequisites(env, testSuite, "tests", testsAndSuites));

    // 1. Add all tests
    for (Target test : testsAndSuites) {
      if (TargetUtils.isTestRule(test)) {
        builder.add(test);
      } else if (strict && !TargetUtils.isTestSuiteRule(test)) {
        // If strict mode is enabled, then give an error for any non-test, non-test-suite targets.
        // TODO(ulfjack): We need to throw to end the process if we happen to be in --nokeep_going,
        // but we can't know whether or not we are at this point.
        env.getListener().handle(Event.error(testSuite.getLocation(),
            "in test_suite rule '" + testSuite.getLabel()
            + "': expecting a test or a test_suite rule but '" + test.getLabel()
            + "' is not one."));
        builder.setError();
      }
    }

    // 2. Add implicit dependencies on tests in same package, if any.
    List<Target> implicitTests = new ArrayList<>();
    builder.mergeError(getPrerequisites(env, testSuite, "$implicit_tests", implicitTests));
    for (Target target : implicitTests) {
      // The Package construction of $implicit_tests ensures that this check never fails, but we
      // add it here anyway for compatibility with future code.
      if (TargetUtils.isTestRule(target)) {
        builder.add(target);
      }
    }

    // 3. Filter based on tags, size, env.
    filterTests(testSuite, builder);

    // 4. Expand all suites recursively.
    for (Target suite : testsAndSuites) {
      if (TargetUtils.isTestSuiteRule(suite)) {
        TestsInSuiteValue value =
            (TestsInSuiteValue) env.getValue(TestsInSuiteValue.key(suite, strict));
        if (value == null) {
          continue;
        }
        builder.merge(value.getTargets());
      }
    }

    return builder.build();
  }

  /**
   * Adds the set of targets found in the attribute named {@code attrName}, which must be of label
   * list type, of the {@code test_suite} rule named {@code testSuite}. Returns true if the method
   * found a problem during the lookup process; the actual error message is reported to the
   * environment.
   */
  private static boolean getPrerequisites(
      Environment env, Rule testSuite, String attrName, List<Target> targets)
      throws InterruptedException {
    List<Label> labels =
        NonconfigurableAttributeMapper.of(testSuite).get(attrName, BuildType.LABEL_LIST);
    Set<PackageIdentifier> pkgIdentifiers = new LinkedHashSet<>();
    for (Label label : labels) {
      pkgIdentifiers.add(label.getPackageIdentifier());
    }
    Map<SkyKey, ValueOrException<BuildFileNotFoundException>> packages = env.getValuesOrThrow(
        PackageValue.keys(pkgIdentifiers), BuildFileNotFoundException.class);
    if (env.valuesMissing()) {
      return false;
    }
    boolean hasError = false;
    Map<PackageIdentifier, Package> packageMap = new HashMap<>();
    for (Entry<SkyKey, ValueOrException<BuildFileNotFoundException>> entry : packages.entrySet()) {
      try {
        packageMap.put(
            (PackageIdentifier) entry.getKey().argument(),
            ((PackageValue) entry.getValue().get()).getPackage());
      } catch (BuildFileNotFoundException e) {
        env.getListener().handle(Event.error(e.getMessage()));
        hasError = true;
      }
    }

    for (Label label : labels) {
      Package pkg = packageMap.get(label.getPackageIdentifier());
      if (pkg == null) {
        continue;
      }
      try {
        targets.add(pkg.getTarget(label.getName()));
      } catch (NoSuchTargetException e) {
        env.getListener().handle(Event.error(e.getMessage()));
        hasError = true;
      }
    }
    return hasError;
  }

  /**
   * Filters 'tests' (by mutation) according to the 'tags' attribute, specifically those that
   * match ALL of the tags in tagsAttribute.
   */
  private static void filterTests(Rule testSuite, ResolvedTargets.Builder<Target> tests) {
    List<String> tagsAttribute =
        NonconfigurableAttributeMapper.of(testSuite).get("tags", Type.STRING_LIST);
    // Split the tags list into positive and negative tags.
    Pair<Collection<String>, Collection<String>> tagLists =
        TestTargetUtils.sortTagsBySense(tagsAttribute);
    final Collection<String> positiveTags = tagLists.first;
    final Collection<String> negativeTags = tagLists.second;

    tests.filter(new Predicate<Target>() {
      @Override
      public boolean apply(@Nullable Target input) {
        Rule test = (Rule) input;
        AttributeMap nonConfigurableAttributes = NonconfigurableAttributeMapper.of(test);
        List<String> testTags =
            new ArrayList<>(nonConfigurableAttributes.get("tags", Type.STRING_LIST));
        testTags.add(nonConfigurableAttributes.get("size", Type.STRING));
        return includeTest(testTags, positiveTags, negativeTags);
      }
    });
  }

  /**
   * Decides whether to include a test in a test_suite or not.
   *
   * @param testTags Collection of all tags exhibited by a given test.
   * @param positiveTags Tags declared by the suite. A Test must match ALL of these.
   * @param negativeTags Tags declared by the suite. A Test must match NONE of these.
   * @return false if the test is to be removed.
   */
  private static boolean includeTest(Collection<String> testTags,
      Collection<String> positiveTags, Collection<String> negativeTags) {
    // Add this test if it matches ALL of the positive tags and NONE of the
    // negative tags in the tags attribute.
    for (String tag : negativeTags) {
      if (testTags.contains(tag)) {
        return false;
      }
    }
    for (String tag : positiveTags) {
      if (!testTags.contains(tag)) {
        return false;
      }
    }
    return true;
  }

  @Nullable
  @Override
  public String extractTag(SkyKey skyKey) {
    return null;
  }
}
