// Copyright 2021 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.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.AspectCollection;
import com.google.devtools.build.lib.analysis.AspectCollection.AspectCycleOnPathException;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.packages.Aspect;
import com.google.devtools.build.lib.packages.AspectClass;
import com.google.devtools.build.lib.packages.AspectDescriptor;
import com.google.devtools.build.lib.packages.AspectsList;
import com.google.devtools.build.lib.packages.NativeAspectClass;
import com.google.devtools.build.lib.packages.StarlarkAspect;
import com.google.devtools.build.lib.packages.StarlarkAspectClass;
import com.google.devtools.build.lib.packages.StarlarkDefinedAspect;
import com.google.devtools.build.lib.server.FailureDetails.Analysis;
import com.google.devtools.build.lib.server.FailureDetails.Analysis.Code;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.skyframe.AspectKeyCreator.AspectKey;
import com.google.devtools.build.lib.skyframe.serialization.VisibleForSerialization;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.util.DetailedExitCode;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyFunctionException;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import net.starlark.java.eval.EvalException;

/**
 * {@link SkyFunction} to load top level aspects, build the dependency relation between them based
 * on the aspects required by the top level aspects and the aspect providers they require and
 * advertise using {@link AspectCollection}.
 *
 * <p>This is needed to compute the relationship between top-level aspects once for all top-level
 * targets in the command. The {@link SkyValue} of this function contains a list of {@link
 * AspectDetails} objects which contain the aspect descriptor and a list of the used aspects this
 * aspect depends on. Then {@link ToplevelStarlarkAspectFunction} adds the target information to
 * create {@link AspectKey}.
 */
final class BuildTopLevelAspectsDetailsFunction implements SkyFunction {

  @Nullable
  @Override
  public SkyValue compute(SkyKey skyKey, Environment env)
      throws BuildTopLevelAspectsDetailsFunctionException, InterruptedException {

    BuildTopLevelAspectsDetailsKey topLevelAspectsDetailsKey =
        (BuildTopLevelAspectsDetailsKey) skyKey.argument();

    ImmutableList<Aspect> topLevelAspects =
        getTopLevelAspects(
            env,
            topLevelAspectsDetailsKey.getTopLevelAspectsClasses(),
            topLevelAspectsDetailsKey.getTopLevelAspectsParameters());

    if (topLevelAspects == null) {
      return null; // some aspects are not loaded
    }

    AspectCollection aspectCollection;
    try {
      aspectCollection = AspectCollection.create(topLevelAspects);
    } catch (AspectCycleOnPathException e) {
      // This exception should never happen because aspects duplicates are not allowed in top-level
      // aspects and their existence should have been caught and reported by `getTopLevelAspects()`.
      env.getListener().handle(Event.error(e.getMessage()));
      throw new BuildTopLevelAspectsDetailsFunctionException(
          new TopLevelAspectsDetailsBuildFailedException(
              e.getMessage(), Code.ASPECT_CREATION_FAILED));
    }
    return new BuildTopLevelAspectsDetailsValue(getTopLevelAspectsDetails(aspectCollection));
  }

  @Nullable
  private static StarlarkDefinedAspect loadStarlarkAspect(
      Environment env, StarlarkAspectClass aspectClass)
      throws InterruptedException, BuildTopLevelAspectsDetailsFunctionException {
    StarlarkDefinedAspect starlarkAspect;
    try {
      BzlLoadValue bzlLoadValue =
          (BzlLoadValue)
              env.getValueOrThrow(
                  AspectFunction.bzlLoadKeyForStarlarkAspect(aspectClass),
                  BzlLoadFailedException.class);
      if (bzlLoadValue == null) {
        return null;
      }
      starlarkAspect = AspectFunction.loadAspectFromBzl(aspectClass, bzlLoadValue);
    } catch (BzlLoadFailedException | AspectCreationException e) {
      env.getListener().handle(Event.error(e.getMessage()));
      throw new BuildTopLevelAspectsDetailsFunctionException(
          new TopLevelAspectsDetailsBuildFailedException(
              e.getMessage(), Code.ASPECT_CREATION_FAILED));
    }
    return starlarkAspect;
  }

  @Nullable
  private static ImmutableList<Aspect> getTopLevelAspects(
      Environment env,
      ImmutableList<AspectClass> topLevelAspectsClasses,
      ImmutableMap<String, String> topLevelAspectsParameters)
      throws InterruptedException, BuildTopLevelAspectsDetailsFunctionException {
    AspectsList.Builder builder = new AspectsList.Builder();

    for (AspectClass aspectClass : topLevelAspectsClasses) {
      if (aspectClass instanceof StarlarkAspectClass) {
        StarlarkAspect starlarkAspect = loadStarlarkAspect(env, (StarlarkAspectClass) aspectClass);
        if (starlarkAspect == null) {
          return null;
        }
        try {
          builder.addAspect(starlarkAspect);
        } catch (EvalException e) {
          env.getListener().handle(Event.error(e.getMessage()));
          throw new BuildTopLevelAspectsDetailsFunctionException(
              new TopLevelAspectsDetailsBuildFailedException(
                  e.getMessage(), Code.ASPECT_CREATION_FAILED));
        }
      } else {
        try {
          builder.addAspect((NativeAspectClass) aspectClass);
        } catch (AssertionError e) {
          env.getListener().handle(Event.error(e.getMessage()));
          throw new BuildTopLevelAspectsDetailsFunctionException(
              new TopLevelAspectsDetailsBuildFailedException(
                  e.getMessage(), Code.ASPECT_CREATION_FAILED));
        }
      }
    }

    AspectsList aspectsList = builder.build();
    try {
        aspectsList.validateTopLevelAspectsParameters(topLevelAspectsParameters);
        return aspectsList.buildAspects(topLevelAspectsParameters);
    } catch (EvalException e) {
      env.getListener().handle(Event.error(e.getMessage()));
      throw new BuildTopLevelAspectsDetailsFunctionException(
          new TopLevelAspectsDetailsBuildFailedException(
              e.getMessage(), Code.ASPECT_CREATION_FAILED));
    }
  }

  private static Collection<AspectDetails> getTopLevelAspectsDetails(
      AspectCollection aspectCollection) {
    Map<AspectDescriptor, AspectDetails> result = new HashMap<>();
    for (AspectCollection.AspectDeps aspectDeps : aspectCollection.getUsedAspects()) {
      buildAspectDetails(aspectDeps, result);
    }
    return result.values();
  }

  private static AspectDetails buildAspectDetails(
      AspectCollection.AspectDeps aspectDeps, Map<AspectDescriptor, AspectDetails> result) {
    if (result.containsKey(aspectDeps.getAspect())) {
      return result.get(aspectDeps.getAspect());
    }

    ImmutableList.Builder<AspectDetails> dependentAspects = ImmutableList.builder();
    for (AspectCollection.AspectDeps path : aspectDeps.getUsedAspects()) {
      dependentAspects.add(buildAspectDetails(path, result));
    }

    AspectDetails aspectDetails =
        new AspectDetails(dependentAspects.build(), aspectDeps.getAspect());
    result.put(aspectDetails.getAspectDescriptor(), aspectDetails);
    return aspectDetails;
  }

  private static final class BuildTopLevelAspectsDetailsFunctionException
      extends SkyFunctionException {
    BuildTopLevelAspectsDetailsFunctionException(TopLevelAspectsDetailsBuildFailedException cause) {
      super(cause, Transience.PERSISTENT);
    }
  }

  private static final class TopLevelAspectsDetailsBuildFailedException extends Exception
      implements SaneAnalysisException {
    private final DetailedExitCode detailedExitCode;

    private TopLevelAspectsDetailsBuildFailedException(String errorMessage, Code code) {
      super(errorMessage);
      this.detailedExitCode =
          DetailedExitCode.of(
              FailureDetail.newBuilder()
                  .setMessage(errorMessage)
                  .setAnalysis(Analysis.newBuilder().setCode(code))
                  .build());
    }

    @Override
    public DetailedExitCode getDetailedExitCode() {
      return detailedExitCode;
    }
  }

  /**
   * Details of the top-level aspects including the {@link AspectDescriptor} and a list of the
   * aspects it depends on. This is used to build the {@link AspectKey} when combined with
   * configured target details.
   */
  static final class AspectDetails {
    private final ImmutableList<AspectDetails> usedAspects;
    private final AspectDescriptor aspectDescriptor;

    private AspectDetails(
        ImmutableList<AspectDetails> usedAspects, AspectDescriptor aspectDescriptor) {
      this.usedAspects = usedAspects;
      this.aspectDescriptor = aspectDescriptor;
    }

    public AspectDescriptor getAspectDescriptor() {
      return aspectDescriptor;
    }

    public ImmutableList<AspectDetails> getUsedAspects() {
      return usedAspects;
    }
  }

  /** {@link SkyKey} for building top-level aspects details. */
  @AutoCodec
  static final class BuildTopLevelAspectsDetailsKey implements SkyKey {
    private static final SkyKeyInterner<BuildTopLevelAspectsDetailsKey> interner =
        SkyKey.newInterner();

    private final ImmutableList<AspectClass> topLevelAspectsClasses;
    private final ImmutableMap<String, String> topLevelAspectsParameters;
    private final int hashCode;

    static BuildTopLevelAspectsDetailsKey create(
        ImmutableList<AspectClass> topLevelAspectsClasses,
        ImmutableMap<String, String> topLevelAspectsParameters) {
      return interner.intern(
          new BuildTopLevelAspectsDetailsKey(
              topLevelAspectsClasses,
              topLevelAspectsParameters,
              Objects.hashCode(topLevelAspectsClasses, topLevelAspectsParameters)));
    }

    @VisibleForSerialization
    @AutoCodec.Interner
    static BuildTopLevelAspectsDetailsKey intern(BuildTopLevelAspectsDetailsKey key) {
      return interner.intern(key);
    }

    private BuildTopLevelAspectsDetailsKey(
        ImmutableList<AspectClass> topLevelAspectsClasses,
        @Nullable ImmutableMap<String, String> topLevelAspectsParameters,
        int hashCode) {
      Preconditions.checkArgument(!topLevelAspectsClasses.isEmpty(), "No aspects");
      this.topLevelAspectsClasses = topLevelAspectsClasses;
      this.topLevelAspectsParameters = topLevelAspectsParameters;
      this.hashCode = hashCode;
    }

    @Override
    public SkyFunctionName functionName() {
      return SkyFunctions.BUILD_TOP_LEVEL_ASPECTS_DETAILS;
    }

    ImmutableList<AspectClass> getTopLevelAspectsClasses() {
      return topLevelAspectsClasses;
    }

    ImmutableMap<String, String> getTopLevelAspectsParameters() {
      return topLevelAspectsParameters;
    }

    @Override
    public int hashCode() {
      return hashCode;
    }

    @Override
    public boolean equals(Object o) {
      if (o == this) {
        return true;
      }
      if (!(o instanceof BuildTopLevelAspectsDetailsKey)) {
        return false;
      }
      BuildTopLevelAspectsDetailsKey that = (BuildTopLevelAspectsDetailsKey) o;
      return hashCode == that.hashCode
          && topLevelAspectsClasses.equals(that.topLevelAspectsClasses)
          && topLevelAspectsParameters.equals(that.topLevelAspectsParameters);
    }

    @Override
    public String toString() {
      return MoreObjects.toStringHelper(this)
          .add("topLevelAspectsClasses", topLevelAspectsClasses)
          .add("topLevelAspectsParameters", topLevelAspectsParameters)
          .toString();
    }

    @Override
    public SkyKeyInterner<BuildTopLevelAspectsDetailsKey> getSkyKeyInterner() {
      return interner;
    }
  }

  /**
   * {@link SkyValue} for {@code BuildTopLevelAspectsDetailsKey} wraps a list of the {@code
   * AspectDetails} of the top level aspects.
   */
  static final class BuildTopLevelAspectsDetailsValue implements SkyValue {
    private final ImmutableList<AspectDetails> aspectsDetails;

    private BuildTopLevelAspectsDetailsValue(Collection<AspectDetails> aspectsDetails) {
      this.aspectsDetails = ImmutableList.copyOf(aspectsDetails);
    }

    public ImmutableList<AspectDetails> getAspectsDetails() {
      return aspectsDetails;
    }
  }
}
