// Copyright 2020 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.bazel.rules.ninja.actions;

import static com.google.common.base.Preconditions.checkState;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.devtools.build.lib.bazel.rules.ninja.file.GenericParsingException;
import com.google.devtools.build.lib.bazel.rules.ninja.parser.NinjaTarget;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;

/**
 * An utility class for gathering non-phony input dependencies of phony {@link NinjaTarget} objects
 * from some Ninja file.
 *
 * <p>Cycles are detected and {@link GenericParsingException} is thrown in that case.
 */
public class NinjaPhonyTargetsUtil {

  private NinjaPhonyTargetsUtil() {}

  @VisibleForTesting
  public static ImmutableSortedMap<PathFragment, PhonyTarget> getPhonyPathsMap(
      ImmutableSortedMap<PathFragment, NinjaTarget> phonyTargets) throws GenericParsingException {
    // There is always a DAG (or forest) of phony targets (as item can be included into several
    // phony targets).
    // This gives us the idea that we can compute any subgraph in the DAG independently, and
    // later include that subgraph into the parent DAG.
    // In the list 'topoOrderedTargets' we will put all the NinjaTargets from the phonyTargets,
    // in the following order: all nodes from a node's subtree are preceding it in a list.
    // This way we can later visit the list "topoOrderedTargets", computing the input files
    // for targets, and for each target K the results for all the phony targets from a subgraph of K
    // will be already computed.
    // The sorting is linear, as we are only checking each input of each node once (we use already).
    List<NinjaTarget> topoOrderedTargets = Lists.newArrayListWithCapacity(phonyTargets.size());
    Set<NinjaTarget> alreadyVisited = Sets.newHashSet();
    for (Map.Entry<PathFragment, NinjaTarget> entry : phonyTargets.entrySet()) {
      NinjaTarget target = entry.getValue();
      topoOrderedTargets.addAll(topoOrderSubGraph(phonyTargets, alreadyVisited, target));
    }

    checkState(topoOrderedTargets.size() == phonyTargets.size());

    SortedMap<PathFragment, PhonyTarget> result = Maps.newTreeMap();
    for (NinjaTarget target : topoOrderedTargets) {
      PathFragment onlyOutput = Iterables.getOnlyElement(target.getAllOutputs());
      ImmutableList.Builder<PathFragment> phonyNames = ImmutableList.builder();
      ImmutableList.Builder<PathFragment> directInputs = ImmutableList.builder();
      Collection<PathFragment> allInputs = target.getAllInputs();
      boolean isAlwaysDirty = allInputs.isEmpty();
      for (PathFragment input : allInputs) {
        NinjaTarget phonyInput = phonyTargets.get(input);
        if (phonyInput != null) {
          // The input is the other phony target.
          // Phony target must have only one output (alias); it is checked during parsing.
          PathFragment phonyName = Iterables.getOnlyElement(phonyInput.getAllOutputs());
          PhonyTarget alreadyComputed = result.get(phonyName);
          Preconditions.checkNotNull(alreadyComputed);
          isAlwaysDirty |= alreadyComputed.isAlwaysDirty();
          phonyNames.add(Iterables.getOnlyElement(phonyInput.getAllOutputs()));
        } else {
          // The input is the usual file.
          directInputs.add(input);
        }
      }
      result.put(
          onlyOutput, new PhonyTarget(phonyNames.build(), directInputs.build(), isAlwaysDirty));
    }

    return ImmutableSortedMap.copyOf(result);
  }

  /**
   * For the given phony NinjaTarget, return a list of all phony NinjaTargets, composing its subtree
   * (direct and transitive inputs). The list is ordered from leaves to their dependents; for any
   * node all its direct and transitive inputs are preceding it in the list.
   *
   * <p>Function does DFS starting from the NinjaTarget, with two phases: in initial processing: 1)
   * if the target was already computed, nothing happens 2) the target is checked for cycle and
   * marked in cycleProtection set, its phony inputs are queued (put in the beginning of the queue)
   * for initial processing 3) the target is queued after its inputs for post-processing in
   * post-processing, the target is recorded into resulting list; all its inputs should have been
   * already written to that list on the previous steps
   */
  private static List<NinjaTarget> topoOrderSubGraph(
      ImmutableSortedMap<PathFragment, NinjaTarget> phonyTargets,
      Set<NinjaTarget> alreadyVisited,
      NinjaTarget target)
      throws GenericParsingException {
    Set<NinjaTarget> cycleProtection = Sets.newHashSet();
    List<NinjaTarget> fragment = Lists.newArrayList();
    ArrayDeque<Pair<NinjaTarget, Boolean>> queue = new ArrayDeque<>();
    queue.add(Pair.of(target, true));
    while (!queue.isEmpty()) {
      Pair<NinjaTarget, Boolean> pair = queue.remove();
      NinjaTarget currentTarget = pair.getFirst();
      if (pair.getSecond()) {
        // Initial processing: checking all the phony inputs of the current target.
        if (alreadyVisited.contains(currentTarget)) {
          continue;
        }
        if (!cycleProtection.add(currentTarget)) {
          throw new GenericParsingException(
              String.format(
                  "Detected a dependency cycle involving the phony target '%s'",
                  Iterables.getOnlyElement(currentTarget.getAllOutputs())));
        }
        // Adding <phony-inputs-of-current-target> for initial processing in front of
        // <current-target>
        // for post-processing into the queue.
        queue.addFirst(Pair.of(currentTarget, false));
        for (PathFragment input : currentTarget.getAllInputs()) {
          NinjaTarget phonyInput = phonyTargets.get(input);
          if (phonyInput != null) {
            queue.addFirst(Pair.of(phonyInput, true));
          }
        }
      } else {
        // Post processing: all inputs should have been processed and added to fragment.
        cycleProtection.remove(currentTarget);
        alreadyVisited.add(currentTarget);
        fragment.add(currentTarget);
      }
    }
    return fragment;
  }
}
