// 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.auto.value.extension.memoized.Memoized;
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. */
  @Memoized
  public ConfiguredTargetKey getConfiguredTargetKey() {
    ConfiguredTargetKey.Builder configuredTargetKeyBuilder =
        ConfiguredTargetKey.builder().setLabel(getLabel()).setConfiguration(getConfiguration());
    if (getExecutionPlatformLabel() != null) {
      configuredTargetKeyBuilder.setExecutionPlatformLabel(getExecutionPlatformLabel());
    }
    return configuredTargetKeyBuilder.build();
  }
}
