// Copyright 2015 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.rules.cpp;

import com.google.common.collect.Lists;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.starlark.StarlarkRuleContext;
import com.google.devtools.build.lib.collect.nestedset.Depset;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.rules.cpp.ExtraLinkTimeLibrary.BuildLibraryOutput;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import net.starlark.java.annot.Param;
import net.starlark.java.annot.StarlarkMethod;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.StarlarkList;
import net.starlark.java.eval.StarlarkThread;
import net.starlark.java.eval.StarlarkValue;
import net.starlark.java.eval.Tuple;

/**
 * A list of extra libraries to include in a link. These are non-C++ libraries that are built from
 * inputs gathered from all the dependencies. The dependencies have no way to coordinate, so each
 * one will add an ExtraLinkTimeLibrary to its CcLinkParams. ExtraLinkTimeLibrary is an interface,
 * and all ExtraLinkTimeLibrary objects of the same class will be gathered together.
 */
public final class ExtraLinkTimeLibraries implements StarlarkValue {
  /**
   * We can have multiple different kinds of lists of libraries to include
   * at link time.  We map from the class type to an actual instance.
   */
  private final Collection<ExtraLinkTimeLibrary> extraLibraries;

  private ExtraLinkTimeLibraries(Collection<ExtraLinkTimeLibrary> extraLibraries) {
    this.extraLibraries = extraLibraries;
  }

  /**
   * Return the set of extra libraries.
   */
  public Collection<ExtraLinkTimeLibrary> getExtraLibraries() {
    return extraLibraries;
  }

  /** Get the set of extra libraries for Starlark. */
  @StarlarkMethod(name = "extra_libraries", documented = false, useStarlarkThread = true)
  public Sequence<ExtraLinkTimeLibrary> getExtraLibrariesForStarlark(StarlarkThread thread)
      throws EvalException {
    CcModule.checkPrivateStarlarkificationAllowlist(thread);
    return StarlarkList.immutableCopyOf(getExtraLibraries());
  }

  public static final Builder builder() {
    return new Builder();
  }

  /**
   * Builder for {@link ExtraLinkTimeLibraries}.
   */
  public static final class Builder {
    private Map<Class<? extends ExtraLinkTimeLibrary>, ExtraLinkTimeLibrary.Builder> libraries =
          new LinkedHashMap<>();

    private Builder() {
      // Nothing to do.
    }

    /**
     * Build a {@link ExtraLinkTimeLibraries} object.
     */
    public ExtraLinkTimeLibraries build() {
      List<ExtraLinkTimeLibrary> extraLibraries = Lists.newArrayList();
      for (ExtraLinkTimeLibrary.Builder builder : libraries.values()) {
        extraLibraries.add(builder.build());
      }
      return new ExtraLinkTimeLibraries(extraLibraries);
    }

    /**
     * Add a transitive dependency.
     */
    public final Builder addTransitive(ExtraLinkTimeLibraries dep) {
      for (ExtraLinkTimeLibrary depLibrary : dep.getExtraLibraries()) {
        Class<? extends ExtraLinkTimeLibrary> c = depLibrary.getClass();
        libraries.computeIfAbsent(c, k -> depLibrary.getBuilder());
        libraries.get(c).addTransitive(depLibrary);
      }
      return this;
    }

    /**
     * Add a single library to build.
     */
    public final Builder add(ExtraLinkTimeLibrary b) {
      Class<? extends ExtraLinkTimeLibrary> c = b.getClass();
      libraries.computeIfAbsent(c, k -> b.getBuilder());
      libraries.get(c).addTransitive(b);
      return this;
    }
  }

  public BuildLibraryOutput buildLibraries(
      RuleContext ruleContext, boolean staticMode, boolean forDynamicLibrary)
      throws InterruptedException, RuleErrorException {
    NestedSetBuilder<CcLinkingContext.LinkerInput> linkerInputs = NestedSetBuilder.linkOrder();
    NestedSetBuilder<Artifact> runtimeLibraries = NestedSetBuilder.linkOrder();
    for (ExtraLinkTimeLibrary extraLibrary : getExtraLibraries()) {
      BuildLibraryOutput buildLibraryOutput =
          extraLibrary.buildLibraries(ruleContext, staticMode, forDynamicLibrary);
      linkerInputs.addTransitive(buildLibraryOutput.getLinkerInputs());
      runtimeLibraries.addTransitive(buildLibraryOutput.getRuntimeLibraries());
    }
    return new BuildLibraryOutput(linkerInputs.build(), runtimeLibraries.build());
  }

  @StarlarkMethod(
      name = "build_libraries",
      documented = false,
      useStarlarkThread = true,
      parameters = {
        @Param(name = "ctx", positional = false, named = true),
        @Param(name = "static_mode", positional = false, named = true),
        @Param(name = "for_dynamic_library", positional = false, named = true),
      })
  public Tuple getBuildLibrariesForStarlark(
      StarlarkRuleContext starlarkRuleContext,
      boolean staticMode,
      boolean forDynamicLibrary,
      StarlarkThread thread)
      throws EvalException {
    CcModule.checkPrivateStarlarkificationAllowlist(thread);
    try {
      BuildLibraryOutput buildLibraryOutput =
          buildLibraries(starlarkRuleContext.getRuleContext(), staticMode, forDynamicLibrary);
      Depset linkerInputs =
          Depset.of(CcLinkingContext.LinkerInput.TYPE, buildLibraryOutput.getLinkerInputs());
      Depset runtimeLibraries = Depset.of(Artifact.TYPE, buildLibraryOutput.getRuntimeLibraries());
      return Tuple.pair(linkerInputs, runtimeLibraries);
    } catch (InterruptedException | RuleErrorException e) {
      throw new EvalException(e);
    }
  }
}
