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

import com.google.auto.value.AutoValue;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.AspectDescriptor;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
import javax.annotation.Nullable;

/**
 * A dependency of a configured target through a label.
 *
 * <p>All instances have an explicit configuration, which includes the target and the configuration
 * of the dependency configured target and any aspects that may be required, as well as the
 * configurations for these aspects and transition keys. {@link Dependency#getTransitionKeys}
 * provides some more context on transition keys.
 *
 * <p>Note that the presence of an aspect here does not necessarily mean that it will be created.
 * They will be filtered based on the {@link TransitiveInfoProvider} instances their associated
 * configured targets have (we cannot do that here because the configured targets are not available
 * yet). No error or warning is reported in this case, because it is expected that rules sometimes
 * over-approximate the providers they supply in their definitions.
 */
@AutoValue
public abstract class Dependency {
  /** Builder to assist in creating dependency instances. */
  @AutoValue.Builder
  public abstract static class Builder {
    /** Sets the label of the target this dependency points to. */
    public abstract Builder setLabel(Label label);

    /** Sets the configuration intended for this dependency. */
    public abstract Builder setConfiguration(BuildConfiguration configuration);

    /** Explicitly set the configuration for this dependency to null. */
    public Builder withNullConfiguration() {
      return setConfiguration(null);
    }

    /** Add aspects to this Dependency. The same configuration is applied to all aspects. */
    public abstract Builder setAspects(AspectCollection aspects);

    /** Sets the keys of a configuration transition. */
    public Builder setTransitionKey(String key) {
      if (key.isEmpty()) {
        // Ignore empty keys.
        return this;
      }
      return setTransitionKeys(ImmutableList.of(key));
    }

    /** Sets the keys of a configuration transition. */
    public abstract Builder setTransitionKeys(ImmutableList<String> keys);

    /**
     * Sets the execution platform {@link Label} that this dependency should use as an override for
     * toolchain resolution.
     */
    public abstract Builder setExecutionPlatformLabel(@Nullable Label executionPlatformLabel);

    // Not public.
    abstract Dependency autoBuild();

    /** Returns the full Dependency instance. */
    public Dependency build() {
      Dependency dependency = autoBuild();
      if (dependency.getConfiguration() == null) {
        Preconditions.checkState(
            dependency.getAspects().equals(AspectCollection.EMPTY),
            "Dependency with null Configuration cannot have aspects");
      }
      return dependency;
    }

    // Added to enable copy, below. Should not be accessible to other classes.
    protected abstract Label getLabel();

    @Nullable
    protected abstract BuildConfiguration getConfiguration();

    protected abstract AspectCollection getAspects();

    protected abstract ImmutableList<String> getTransitionKeys();

    /** Returns a copy of this Builder, with the values the same. */
    public Builder copy() {
      return Dependency.builder()
          .setLabel(getLabel())
          .setConfiguration(getConfiguration())
          .setAspects(getAspects())
          .setTransitionKeys(getTransitionKeys());
    }
  }

  /** Returns a new {@link Builder} to create {@link Dependency} instances. */
  public static Builder builder() {
    return new AutoValue_Dependency.Builder()
        .setAspects(AspectCollection.EMPTY)
        .setTransitionKeys(ImmutableList.of());
  }

  /** Returns the label of the target this dependency points to. */
  public abstract Label getLabel();

  /** Returns the explicit configuration intended for this dependency. */
  @Nullable
  public abstract BuildConfiguration getConfiguration();

  /**
   * Returns the set of aspects which should be evaluated and combined with the configured target
   * pointed to by this dependency.
   *
   * @see #getAspectConfiguration(AspectDescriptor)
   */
  public abstract AspectCollection getAspects();

  /** Returns the configuration an aspect should be evaluated with. */
  @Nullable
  public BuildConfiguration getAspectConfiguration(AspectDescriptor aspect) {
    return getConfiguration();
  }

  /**
   * Returns the keys of a configuration transition, if any exist, associated with this dependency.
   * See {@link ConfigurationTransition#apply} for more details. Normally, this returns an empty
   * list, when there was no configuration transition in effect, or one with a single entry, when
   * there was a specific configuration transition result that led to this. It may also return a
   * list with multiple entries if the dependency has a null configuration, yet the outgoing edge
   * has a split transition. In such cases all transition keys returned by the transition are tagged
   * to the dependency.
   */
  public abstract ImmutableList<String> getTransitionKeys();

  /**
   * Returns the execution platform {@link Label} that this dependency should use as an override for
   * toolchain resolution.
   */
  @Nullable
  public abstract Label getExecutionPlatformLabel();

  /** Returns the ConfiguredTargetKey needed to fetch this dependency. */
  public ConfiguredTargetKey getConfiguredTargetKey() {
    ConfiguredTargetKey.Builder configuredTargetKeyBuilder =
        ConfiguredTargetKey.builder().setLabel(getLabel()).setConfiguration(getConfiguration());
    if (getExecutionPlatformLabel() != null) {
      configuredTargetKeyBuilder.setExecutionPlatformLabel(getExecutionPlatformLabel());
    }
    return configuredTargetKeyBuilder.build();
  }
}
