// 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.BuildConfigurationValue;
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(BuildConfigurationValue 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 BuildConfigurationValue 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 BuildConfigurationValue 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 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();
  }
}
