/*
 * 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.test.result.groups;

import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.TestRule;
import com.facebook.buck.test.TestResults;
import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;

import java.util.LinkedList;
import java.util.Map;
import java.util.Set;

/**
 * Group TestResults together into cliques based on the graph built by following 'deps' and
 * 'source_under_test' edges.
 */
public class TestResultsGrouper {

  // Maps a library to a set of tests that test it.
  private final SetMultimap<BuildRule, TestRule> testRulesForBuildRules = HashMultimap.create();

  // Maps a test to a set of libraries it *indirectly* depends on.
  private final SetMultimap<TestRule, BuildRule> allAncestorDependenciesForTestRule =
      HashMultimap.create();

  // Maps a test onto its results, as given to us by post().
  private final Map<TestRule, TestResults> allTestResults = Maps.newHashMap();

  // The set of tests we've already grouped-and-flushed.
  private final Set<TestRule> flushedTestRules = Sets.newHashSet();

  // The set of tests we've seen, but not yet been able to group-and-flush.
  private final Set<TestRule> pendingTestRules = Sets.newHashSet();

  public TestResultsGrouper(Iterable<TestRule> testRules) {
    for (TestRule testRule : testRules) {
      allTestResults.put(testRule, null);

      ImmutableSet<BuildRule> sourcesUnderTest = testRule.getSourceUnderTest();
      for (BuildRule buildRule : sourcesUnderTest) {
        // We have found the (test => library) edge, so store the inverse (library => test) edge.
        testRulesForBuildRules.put(buildRule, testRule);

        // Store all the ancestor dependencies (but not the direct dependency).
        for (BuildRule dep : getAllDependencies(buildRule)) {
          if (dep != buildRule) {
            allAncestorDependenciesForTestRule.put(testRule, dep);
          }
        }
      }
    }
  }

  /**
   * Accept and enqueue a set of TestResults for the given TestRule.  When enough results have been
   * received that complete cliques of test-rule / test-results can be formed, they are returned.
   *
   * @param finishedTest The test that just finished.
   * @param testResults The test's results.
   * @return The TestResults (keyed by respective TestRules) which, as a result of this most recent
   *     test result, now form complete cliques.
   */
  public synchronized Map<TestRule, TestResults> post(
      TestRule finishedTest,
      TestResults testResults) {
    String targetName = finishedTest.getBuildTarget().getFullyQualifiedName();
    Preconditions.checkState(allTestResults.containsKey(finishedTest),
        "Unexpected test results found for test '%s'", targetName);
    Preconditions.checkState(allTestResults.get(finishedTest) == null,
        "Duplicate test results found for test '%s'", targetName);

    allTestResults.put(finishedTest, testResults);
    pendingTestRules.add(finishedTest);

    return ImmutableMap.copyOf(flush());
  }

  ImmutableSet<BuildRule> getAllDependencies(BuildRule rootBuildRule) {
    Set<BuildRule> allDeps = Sets.newHashSet();
    Set<BuildRule> seen = Sets.newHashSet();
    LinkedList<BuildRule> queue = new LinkedList<>();
    queue.add(rootBuildRule);
    while (!queue.isEmpty()) {
      BuildRule node = queue.remove();
      allDeps.add(node);
      for (BuildRule child : node.getDeps()) {
        if (seen.add(child)) {
          queue.add(child);
        }
      }
    }
    return ImmutableSet.copyOf(allDeps);
  }

  private Set<TestRule> getDependentTestRules(TestRule testRule) {
    ImmutableSet.Builder<TestRule> dependentTestRulesBuilder = new ImmutableSet.Builder<>();
    Set<BuildRule> deps = allAncestorDependenciesForTestRule.get(testRule);
    for (BuildRule dep : deps) {
      // Dependencies may not necessarily have a TestRule that tests them.
      //
      //   BuildRules: :parent ----> :child ----> :grandchild
      //   TestRules:  ^ParentTest  ^ChildTest
      //
      // It might be that no one wrote a test (:grandchild) or this test run wasn't asked to include
      // the relevant test ("buck test :parent").
      //
      if (testRulesForBuildRules.containsKey(dep)) {
        Set<TestRule> dependentTestRules = testRulesForBuildRules.get(dep);
        dependentTestRulesBuilder.addAll(dependentTestRules);
      }
    }
    return dependentTestRulesBuilder.build();
  }

  private Map<TestRule, TestResults> flush() {
    Map<TestRule, TestResults> result = Maps.newHashMap();

    for (TestRule pendingTestRule : pendingTestRules) {
      Map<TestRule, TestResults> toAdd = flushOne(pendingTestRule);
      for (TestRule flushableTestRule : toAdd.keySet()) {
        if (!flushedTestRules.contains(flushableTestRule)) {
          TestResults flushableTestResults = toAdd.get(flushableTestRule);
          result.put(flushableTestRule, flushableTestResults);
          flushedTestRules.add(flushableTestRule);
        }
      }
    }

    pendingTestRules.removeAll(flushedTestRules);

    return result;
  }

  /**
   * The returned Map may contain test results that we've already flushed.
   *
   * For example, if we have Parent depending on Child, with a ParentTest and ChildTest, the
   * ChildTest may flush (child-results) first (it has no dependencies), and the ParentTest will
   * build the set (parent-results, child-results), but we should not re-flush child-results.
   */
  private Map<TestRule, TestResults> flushOne(TestRule ourTestRule) {
    Map<TestRule, TestResults> result = Maps.newHashMap();

    TestResults ourTestResults = Preconditions.checkNotNull(allTestResults.get(ourTestRule));
    result.put(ourTestRule, ourTestResults);

    int failedDepsCount = 0;
    Set<TestRule> dependentTestRules = getDependentTestRules(ourTestRule);
    for (TestRule dependentTestRule : dependentTestRules) {
      TestResults dependentTestResults = allTestResults.get(dependentTestRule);
      if (dependentTestResults == null) {
        return ImmutableMap.of();
      } else {
        if (!dependentTestResults.isSuccess()) {
          failedDepsCount++;
        }
        result.put(dependentTestRule, dependentTestResults);
      }
    }

    ourTestResults.setDependenciesPassTheirTests(failedDepsCount == 0);

    return result;
  }
}
