/*
 * 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.rules;

import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.HasSourceUnderTest;
import com.facebook.buck.util.HumanReadableException;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;

public class TargetGraphAndTargets {
  private final TargetGraph targetGraph;
  private final ImmutableSet<TargetNode<?>> projectRoots;
  private final ImmutableSet<TargetNode<?>> associatedTests;

  private TargetGraphAndTargets(
      TargetGraph targetGraph,
      Iterable<TargetNode<?>> projectRoots,
      Iterable<TargetNode<?>> associatedTests) {
    this.targetGraph = targetGraph;
    this.projectRoots = ImmutableSet.copyOf(projectRoots);
    this.associatedTests = ImmutableSet.copyOf(associatedTests);
  }

  public TargetGraph getTargetGraph() {
    return targetGraph;
  }

  public ImmutableSet<TargetNode<?>> getProjectRoots() {
    return projectRoots;
  }

  public ImmutableSet<TargetNode<?>> getAssociatedTests() {
    return associatedTests;
  }

  public static ImmutableSet<BuildTarget> getExplicitTestTargets(
      ImmutableSet<BuildTarget> buildTargets,
      TargetGraph projectGraph) {
    ImmutableSet<TargetNode<?>> projectRoots = checkAndGetTargetNodes(buildTargets, projectGraph);
    return FluentIterable
        .from(projectGraph.getSubgraph(projectRoots).getNodes())
        .transformAndConcat(
            new Function<TargetNode<?>, Iterable<BuildTarget>>() {
              @Override
              public Iterable<BuildTarget> apply(TargetNode<?> node) {
                return TargetNodes.getTestTargetsForNode(node);
              }
            })
        .toSet();
  }

  private static ImmutableSet<TargetNode<?>> checkAndGetTargetNodes(
      ImmutableSet<BuildTarget> buildTargets,
      TargetGraph projectGraph) {
    ImmutableSet.Builder<TargetNode<?>> targetNodesBuilder = ImmutableSet.builder();
    for (BuildTarget target : buildTargets) {
      TargetNode<?> targetNode = projectGraph.get(target);
      if (targetNode == null) {
        throw new HumanReadableException("Target '%s' does not exist.", target);
      }
      targetNodesBuilder.add(targetNode);
    }
    return targetNodesBuilder.build();
  }

  public static TargetGraphAndTargets create(
      ImmutableSet<BuildTarget> graphRoots,
      TargetGraph projectGraph,
      AssociatedTargetNodePredicate associatedProjectPredicate,
      boolean isWithTests,
      ImmutableSet<BuildTarget> explicitTests) {
    // Get the roots of the main graph. This contains all the targets in the project slice, or all
    // the valid project roots if a project slice is not specified.
    ImmutableSet<TargetNode<?>> projectRoots = checkAndGetTargetNodes(graphRoots, projectGraph);

    // Optionally get the roots of the test graph. This contains all the tests that cover the roots
    // of the main graph or their dependencies.
    ImmutableSet<TargetNode<?>> associatedTests = ImmutableSet.of();
    if (isWithTests) {
      AssociatedTargetNodePredicate associatedTestsPredicate = new AssociatedTargetNodePredicate() {
        @Override
        public boolean apply(TargetNode<?> targetNode, TargetGraph targetGraph) {
          if (!targetNode.getType().isTestRule()) {
            return false;
          }
          ImmutableSortedSet<BuildTarget> sourceUnderTest;
          if (targetNode.getConstructorArg() instanceof HasSourceUnderTest) {
            HasSourceUnderTest argWithSourceUnderTest =
                (HasSourceUnderTest) targetNode.getConstructorArg();
            sourceUnderTest = argWithSourceUnderTest.getSourceUnderTest();
          } else {
            return false;
          }

          for (BuildTarget buildTargetUnderTest : sourceUnderTest) {
            if (targetGraph.get(buildTargetUnderTest) != null) {
              return true;
            }
          }

          return false;
        }
      };

      associatedTests = ImmutableSet.copyOf(
          Sets.union(
              ImmutableSet.copyOf(
                  projectGraph.getAll(explicitTests)),
              getAssociatedTargetNodes(
                  projectGraph,
                  projectRoots,
                  associatedTestsPredicate)
          )
      );
    }

    ImmutableSet<TargetNode<?>> associatedProjects = getAssociatedTargetNodes(
        projectGraph,
        Iterables.concat(projectRoots, associatedTests),
        associatedProjectPredicate);

    TargetGraph targetGraph = projectGraph.getSubgraph(
        Iterables.concat(projectRoots, associatedTests, associatedProjects));

    return new TargetGraphAndTargets(targetGraph, projectRoots, associatedTests);
  }

  /**
   * @param projectGraph A TargetGraph containing all nodes that could be related.
   * @param subgraphRoots Target nodes forming the roots of the subgraph to which the returned nodes
   *                      are related.
   * @param associatedTargetNodePredicate A predicate to determine whether a node is related or not.
   * @return A set of nodes related to {@code subgraphRoots} or their dependencies.
   */
  private static ImmutableSet<TargetNode<?>> getAssociatedTargetNodes(
      TargetGraph projectGraph,
      Iterable<TargetNode<?>> subgraphRoots,
      final AssociatedTargetNodePredicate associatedTargetNodePredicate) {
    final TargetGraph subgraph = projectGraph.getSubgraph(subgraphRoots);

    return FluentIterable
        .from(projectGraph.getNodes())
        .filter(
            new Predicate<TargetNode<?>>() {
              @Override
              public boolean apply(TargetNode<?> node) {
                return associatedTargetNodePredicate.apply(node, subgraph);
              }
            })
        .toSet();
  }
}
