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

import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.actions.ActionLookupKey;
import com.google.devtools.build.lib.analysis.ConfiguredTargetValue;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.packages.PackageGroup;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.pkgcache.PackageProvider;
import com.google.devtools.build.lib.skyframe.AspectKeyCreator.AspectKey;
import com.google.devtools.build.skyframe.CycleInfo;
import com.google.devtools.build.skyframe.SkyKey;
import java.util.List;

/**
 * Reports cycles between targets. These may be in the form of {@link ConfiguredTargetValue}s or
 * {@link TransitiveTargetValue}s.
 */
class TargetCycleReporter extends AbstractLabelCycleReporter {

  private static final Predicate<SkyKey> CONFIGURED_TARGET_OR_TRANSITIVE_RDEP =
      Predicates.or(
          SkyFunctions.isSkyFunction(SkyFunctions.CONFIGURED_TARGET),
          SkyFunctions.isSkyFunction(SkyFunctions.ASPECT),
          SkyFunctions.isSkyFunction(SkyFunctions.TOP_LEVEL_ASPECTS),
          SkyFunctions.isSkyFunction(TransitiveTargetKey.NAME),
          SkyFunctions.isSkyFunction(SkyFunctions.PREPARE_ANALYSIS_PHASE),
          SkyFunctions.isSkyFunction(SkyFunctions.BUILD_DRIVER));

  TargetCycleReporter(PackageProvider packageProvider) {
    super(packageProvider);
  }

  @Override
  protected boolean shouldSkipOnPathToCycle(SkyKey key) {
    return SkyFunctions.PREPARE_ANALYSIS_PHASE.equals(key.functionName())
        // BuildDriverKeys don't provide any relevant info for the end user.
        || SkyFunctions.BUILD_DRIVER.equals(key.functionName());
  }

  @Override
  protected boolean canReportCycle(SkyKey topLevelKey, CycleInfo cycleInfo) {
    return CONFIGURED_TARGET_OR_TRANSITIVE_RDEP.apply(topLevelKey)
        && cycleInfo.getPathToCycle().stream().allMatch(CONFIGURED_TARGET_OR_TRANSITIVE_RDEP)
        && cycleInfo.getCycle().stream().allMatch(CONFIGURED_TARGET_OR_TRANSITIVE_RDEP);
  }

  @Override
  public String prettyPrint(Object key) {
    if (key instanceof ConfiguredTargetKey) {
      return ((ConfiguredTargetKey) key).prettyPrint();
    } else if (key instanceof AspectKey) {
      return ((AspectKey) key).prettyPrint();
    } else {
      return getLabel((SkyKey) key).toString();
    }
  }

  @Override
  public Label getLabel(SkyKey key) {
    if (key instanceof ActionLookupKey) {
      return Preconditions.checkNotNull(((ActionLookupKey) key.argument()).getLabel(), key);
    } else if (key instanceof TransitiveTargetKey) {
      return ((TransitiveTargetKey) key).getLabel();
    } else {
      throw new UnsupportedOperationException(key.toString());
    }
  }

  @Override
  protected String getAdditionalMessageAboutCycle(
      ExtendedEventHandler eventHandler, SkyKey topLevelKey, CycleInfo cycleInfo) {
    List<SkyKey> keys = Lists.newArrayList();
    if (!cycleInfo.getPathToCycle().isEmpty()) {
      if (!shouldSkipOnPathToCycle(topLevelKey)) {
        keys.add(topLevelKey);
      }
      cycleInfo.getPathToCycle().stream()
          .filter(key -> !shouldSkipOnPathToCycle(key))
          .forEach(keys::add);
    }
    keys.addAll(cycleInfo.getCycle());
    // Make sure we check the edge from the last element of the cycle to the first element of the
    // cycle.
    keys.add(cycleInfo.getCycle().get(0));

    Target currentTarget = getTargetForLabel(eventHandler, getLabel(keys.get(0)));
    for (SkyKey nextKey : keys) {
      Label nextLabel = getLabel(nextKey);
      Target nextTarget = getTargetForLabel(eventHandler, nextLabel);
      // TODO(aranguyen): remove this code as a result of b/128716030
      // This is inefficient but it's no big deal since we only do this when there's a cycle.
      if (!nextTarget.getTargetKind().equals(PackageGroup.targetKind())
          && Iterables.contains(currentTarget.getVisibilityDependencyLabels(), nextLabel)) {
        return "\nThe cycle is caused by a visibility edge from "
            + currentTarget.getLabel()
            + " to the non-package_group target "
            + nextTarget.getLabel()
            + ". Note that "
            + "visibility labels are supposed to be package_group targets, which prevents cycles "
            + "of this form.";
      }
      currentTarget = nextTarget;
    }
    return "";
  }
}
