// Copyright 2022 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.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.bazel.bzlmod.BzlmodRepoRuleValue;
import com.google.devtools.build.lib.bazel.bzlmod.ModuleExtensionId;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.repository.RequestRepositoryInformationEvent;
import com.google.devtools.build.lib.rules.repository.RepositoryDirectoryValue;
import com.google.devtools.build.skyframe.CycleInfo;
import com.google.devtools.build.skyframe.CyclesReporter;
import com.google.devtools.build.skyframe.SkyKey;

/** Reports cycles introduced by module extensions and .bzl files where they are declared. */
public class BzlmodRepoCycleReporter implements CyclesReporter.SingleCycleReporter {

  private static final Predicate<SkyKey> IS_BZL_LOAD =
      SkyFunctions.isSkyFunction(SkyFunctions.BZL_LOAD);

  private static final Predicate<SkyKey> IS_PACKAGE_LOOKUP =
      SkyFunctions.isSkyFunction(SkyFunctions.PACKAGE_LOOKUP);

  private static final Predicate<SkyKey> IS_CONTAINING_PACKAGE =
      SkyFunctions.isSkyFunction(SkyFunctions.CONTAINING_PACKAGE_LOOKUP);

  private static final Predicate<SkyKey> IS_REPOSITORY_DIRECTORY =
      SkyFunctions.isSkyFunction(SkyFunctions.REPOSITORY_DIRECTORY);

  private static final Predicate<SkyKey> IS_REPO_RULE =
      SkyFunctions.isSkyFunction(BzlmodRepoRuleValue.BZLMOD_REPO_RULE);

  private static final Predicate<SkyKey> IS_EXTENSION_IMPL =
      SkyFunctions.isSkyFunction(SkyFunctions.SINGLE_EXTENSION_EVAL);

  private static void requestRepoDefinitions(
      ExtendedEventHandler eventHandler, Iterable<SkyKey> repos) {
    for (SkyKey repo : repos) {
      if (repo instanceof RepositoryDirectoryValue.Key) {
        eventHandler.post(
            new RequestRepositoryInformationEvent(
                ((RepositoryDirectoryValue.Key) repo).argument().getName()));
      }
    }
  }

  @Override
  public boolean maybeReportCycle(
      SkyKey topLevelKey,
      CycleInfo cycleInfo,
      boolean alreadyReported,
      ExtendedEventHandler eventHandler) {
    ImmutableList<SkyKey> cycle = cycleInfo.getCycle();
    if (alreadyReported) {
      return true;
    }

    // This cycle reporter is aimed to handle cycles between any chaining of general .bzl
    // files, extension-generated repositories, extension evaluations, and the .bzl files where
    // they are declared. The state machine that describes this kind of cycles is:
    //    ________________________
    //   V                        |
    // PACKAGE -> REPOSITORY -> EXT -> BZL_LOAD -
    //                   ^                   ^   \
    //                   |___________________|___|
    // TODO(andreisolo): Figure out how to detect and print this kind of cycles more specifically.
    if (Iterables.all(
        cycle,
        Predicates.or(
            IS_REPOSITORY_DIRECTORY,
            IS_PACKAGE_LOOKUP,
            IS_REPO_RULE,
            IS_EXTENSION_IMPL,
            IS_BZL_LOAD,
            IS_CONTAINING_PACKAGE))) {
      StringBuilder cycleMessage =
          new StringBuilder(
              "Circular definition of repositories generated by module extensions and/or .bzl"
                  + " files:");
      Iterable<SkyKey> repos =
          Iterables.filter(
              cycle, Predicates.or(IS_REPOSITORY_DIRECTORY, IS_EXTENSION_IMPL, IS_BZL_LOAD));
      Function<SkyKey, String> printer =
          input -> {
            if (input instanceof RepositoryDirectoryValue.Key) {
              return ((RepositoryDirectoryValue.Key) input).argument().getNameWithAt();
            } else if (input.argument() instanceof ModuleExtensionId) {
              ModuleExtensionId id = (ModuleExtensionId) input.argument();
              return String.format(
                  "extension '%s' defined in %s",
                  id.getExtensionName(), id.getBzlFileLabel().getCanonicalForm());
            } else {
              Preconditions.checkArgument(input.argument() instanceof BzlLoadValue.Key);
              return ((BzlLoadValue.Key) input.argument()).getLabel().toString();
            }
          };
      AbstractLabelCycleReporter.printCycle(ImmutableList.copyOf(repos), cycleMessage, printer);
      eventHandler.handle(Event.error(null, cycleMessage.toString()));
      // To help debugging, request that the information be printed about where the respective
      // repositories were defined.
      requestRepoDefinitions(eventHandler, repos);
      return true;
    } else if (Iterables.any(cycle, IS_BZL_LOAD)) {
      Label fileLabel =
          ((BzlLoadValue.Key) Iterables.getLast(Iterables.filter(cycle, IS_BZL_LOAD))).getLabel();
      eventHandler.handle(
          Event.error(
              null,
              String.format(
                  "Failed to load .bzl file '%s': possible dependency cycle detected.\n",
                  fileLabel)));
      return true;
    } else if (Iterables.any(cycle, IS_PACKAGE_LOOKUP)) {
      PackageIdentifier pkg =
          (PackageIdentifier)
              Iterables.getLast(Iterables.filter(cycle, IS_PACKAGE_LOOKUP)).argument();
      eventHandler.handle(
          Event.error(
              null,
              String.format(
                  "cannot load package '%s': possible dependency cycle detected.\n", pkg)));
      return true;
    }
    return false;
  }
}
