// Copyright 2014 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.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.DependencyResolver;
import com.google.devtools.build.lib.analysis.TargetAndConfiguration;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.FragmentClassSet;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.causes.Cause;
import com.google.devtools.build.lib.causes.LoadingFailedCause;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.packages.NoSuchThingException;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.skyframe.SkyFunction.Environment;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.ValueOrException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;

/**
 * A dependency resolver for use within Skyframe. Loads packages lazily when possible.
 */
public final class SkyframeDependencyResolver extends DependencyResolver {

  private final Environment env;

  public SkyframeDependencyResolver(Environment env) {
    this.env = env;
  }

  @Override
  protected void invalidVisibilityReferenceHook(TargetAndConfiguration value, Label label) {
    env.getListener().handle(
        Event.error(TargetUtils.getLocationMaybe(value.getTarget()), String.format(
            "Label '%s' in visibility attribute does not refer to a package group", label)));
  }

  @Override
  protected void invalidPackageGroupReferenceHook(TargetAndConfiguration value, Label label) {
    env.getListener().handle(
        Event.error(TargetUtils.getLocationMaybe(value.getTarget()), String.format(
            "label '%s' does not refer to a package group", label)));
  }

  @Override
  protected void missingEdgeHook(Target from, Label to, NoSuchThingException e)
      throws InterruptedException {
    if (e instanceof NoSuchTargetException) {
      NoSuchTargetException nste = (NoSuchTargetException) e;
      if (to.equals(nste.getLabel())) {
        env.getListener().handle(
            Event.error(
                TargetUtils.getLocationMaybe(from),
                TargetUtils.formatMissingEdge(from, to, e)));
      }
    } else if (e instanceof NoSuchPackageException) {
      NoSuchPackageException nspe = (NoSuchPackageException) e;
      if (nspe.getPackageId().equals(to.getPackageIdentifier())) {
        env.getListener().handle(
            Event.error(
                TargetUtils.getLocationMaybe(from),
                TargetUtils.formatMissingEdge(from, to, e)));
      }
    }
  }

  @Nullable
  @Override
  protected Target getTarget(Target from, Label label, NestedSetBuilder<Cause> rootCauses)
      throws InterruptedException {
    SkyKey key = PackageValue.key(label.getPackageIdentifier());
    PackageValue packageValue;
    try {
      packageValue = (PackageValue) env.getValueOrThrow(key, NoSuchPackageException.class);
    } catch (NoSuchPackageException e) {
      rootCauses.add(new LoadingFailedCause(label, e.getMessage()));
      missingEdgeHook(from, label, e);
      return null;
    }
    if (packageValue == null) {
      return null;
    }
    Package pkg = packageValue.getPackage();
    try {
      Target target = pkg.getTarget(label.getName());
      if (pkg.containsErrors()) {
        NoSuchTargetException e = new NoSuchTargetException(target);
        missingEdgeHook(from, label, e);
        if (target != null) {
          rootCauses.add(new LoadingFailedCause(label, e.getMessage()));
          return target;
        } else {
          return null;
        }
      }
      return target;
    } catch (NoSuchTargetException e) {
      rootCauses.add(new LoadingFailedCause(label, e.getMessage()));
      missingEdgeHook(from, label, e);
      return null;
    }
  }

  @Nullable
  @Override
  protected List<BuildConfiguration> getConfigurations(
      FragmentClassSet fragments,
      Iterable<BuildOptions> buildOptions,
      BuildOptions defaultBuildOptions)
      throws InvalidConfigurationException, InterruptedException {
    List<SkyKey> keys = new ArrayList<>();
    for (BuildOptions options : buildOptions) {
      keys.add(
          BuildConfigurationValue.key(
              fragments, BuildOptions.diffForReconstruction(defaultBuildOptions, options)));
    }
    Map<SkyKey, ValueOrException<InvalidConfigurationException>> configValues =
        env.getValuesOrThrow(keys, InvalidConfigurationException.class);
    if (env.valuesMissing()) {
      return null;
    }
    ImmutableList.Builder<BuildConfiguration> result = ImmutableList.builder();
    for (SkyKey key : keys) {
      result.add(((BuildConfigurationValue) configValues.get(key).get()).getConfiguration());
    }
    return result.build();
  }
}
