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

import com.google.common.base.Preconditions;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.LicensesProvider;
import com.google.devtools.build.lib.analysis.LicensesProviderImpl;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
import com.google.devtools.build.lib.analysis.RequiredConfigFragmentsProvider;
import com.google.devtools.build.lib.analysis.TargetContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
import com.google.devtools.build.lib.analysis.test.InstrumentedFilesInfo;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.packages.OutputFile;
import com.google.devtools.build.lib.packages.PackageSpecification.PackageGroupContents;
import com.google.devtools.build.lib.skyframe.BuildConfigurationValue;
import net.starlark.java.eval.Printer;

/** A ConfiguredTarget for an OutputFile. */
@Immutable
public class OutputFileConfiguredTarget extends FileConfiguredTarget {

  private final Artifact artifact;
  private final ConfiguredTarget generatingRule;

  public OutputFileConfiguredTarget(
      TargetContext targetContext,
      OutputFile outputFile,
      ConfiguredTarget generatingRule,
      Artifact outputArtifact) {
    this(
        targetContext.getLabel(),
        targetContext.getConfigurationKey(),
        targetContext.getVisibility(),
        outputArtifact,
        generatingRule);
    Preconditions.checkArgument(targetContext.getTarget() == outputFile);
  }

  private OutputFileConfiguredTarget(
      Label label,
      BuildConfigurationValue.Key configurationKey,
      NestedSet<PackageGroupContents> visibility,
      Artifact artifact,
      ConfiguredTarget generatingRule) {

    super(
        label,
        configurationKey,
        visibility,
        artifact,
        instrumentedFilesInfo(generatingRule),
        generatingRule.getProvider(RequiredConfigFragmentsProvider.class),
        Preconditions.checkNotNull(generatingRule).get(OutputGroupInfo.STARLARK_CONSTRUCTOR));

    this.artifact = artifact;
    this.generatingRule = Preconditions.checkNotNull(generatingRule);
  }

  private static InstrumentedFilesInfo instrumentedFilesInfo(
      TransitiveInfoCollection generatingRule) {
    Preconditions.checkNotNull(generatingRule);
    InstrumentedFilesInfo provider = generatingRule.get(InstrumentedFilesInfo.STARLARK_CONSTRUCTOR);
    return provider == null ? InstrumentedFilesInfo.EMPTY : provider;
  }

  public ConfiguredTarget getGeneratingRule() {
    return generatingRule;
  }

  @Override
  public final Artifact getArtifact() {
    return artifact;
  }

  @Override
  public NestedSet<TargetLicense> getTransitiveLicenses() {
    return getProvider(LicensesProvider.class, LicensesProviderImpl.EMPTY)
        .getTransitiveLicenses();
  }

  @Override
  public TargetLicense getOutputLicenses() {
    return getProvider(LicensesProvider.class, LicensesProviderImpl.EMPTY)
        .getOutputLicenses();
  }

  @Override
  public boolean hasOutputLicenses() {
    return getProvider(LicensesProvider.class, LicensesProviderImpl.EMPTY)
        .hasOutputLicenses();
  }

  /**
   * Returns the corresponding provider from the generating rule, if it is non-null, or {@code
   * defaultValue} otherwise.
   */
  private <T extends TransitiveInfoProvider> T getProvider(Class<T> clazz, T defaultValue) {
    if (generatingRule != null) {
      T result = generatingRule.getProvider(clazz);
      if (result != null) {
        return result;
      }
    }
    return defaultValue;
  }

  @Override
  public void repr(Printer printer) {
    printer.append("<output file target " + getLabel() + ">");
  }
}
