// 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.rules.objc;

import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.collect.nestedset.Depset;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import javax.annotation.Nullable;
import net.starlark.java.annot.StarlarkMethod;
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.StarlarkList;
import net.starlark.java.eval.StarlarkValue;

/**
 * Artifacts related to compilation. Any rule containing compilable sources will create an instance
 * of this class.
 */
final class CompilationArtifacts implements StarlarkValue {
  static class Builder {
    // TODO(bazel-team): Should these be sets instead of just iterables?
    private Iterable<Artifact> srcs = ImmutableList.of();
    private Iterable<Artifact> nonArcSrcs = ImmutableList.of();
    private NestedSetBuilder<Artifact> additionalHdrs = NestedSetBuilder.stableOrder();
    private Iterable<Artifact> privateHdrs = ImmutableList.of();
    private Iterable<Artifact> precompiledSrcs = ImmutableList.of();
    private IntermediateArtifacts intermediateArtifacts;

    @CanIgnoreReturnValue
    Builder addSrcs(Iterable<Artifact> srcs) {
      this.srcs = Iterables.concat(this.srcs, srcs);
      return this;
    }

    @CanIgnoreReturnValue
    Builder addNonArcSrcs(Iterable<Artifact> nonArcSrcs) {
      this.nonArcSrcs = Iterables.concat(this.nonArcSrcs, nonArcSrcs);
      return this;
    }

    /**
     * Adds header artifacts that should be directly accessible to dependers, but aren't specified
     * in the hdrs attribute. Note that the underlying infrastructure may flatten the nested set.
     */
    @CanIgnoreReturnValue
    Builder addAdditionalHdrs(NestedSet<Artifact> additionalHdrs) {
      this.additionalHdrs.addTransitive(additionalHdrs);
      return this;
    }

    /**
     * Adds header artifacts that should be directly accessible to dependers, but aren't specified
     * in the hdrs attribute.
     */
    @CanIgnoreReturnValue
    Builder addAdditionalHdrs(Iterable<Artifact> additionalHdrs) {
      this.additionalHdrs.addAll(additionalHdrs);
      return this;
    }

    /**
     * Adds header artifacts that should not be directly accessible to dependers. {@code
     * privateHdrs} should not be a {@link NestedSet}, as it will be flattened when added.
     */
    @CanIgnoreReturnValue
    Builder addPrivateHdrs(Iterable<Artifact> privateHdrs) {
      this.privateHdrs = Iterables.concat(this.privateHdrs, privateHdrs);
      return this;
    }

    /** Adds precompiled sources (.o files). */
    @CanIgnoreReturnValue
    Builder addPrecompiledSrcs(Iterable<Artifact> precompiledSrcs) {
      // TODO(ulfjack): These are ignored *except* for a check below whether they are empty.
      this.precompiledSrcs = Iterables.concat(this.precompiledSrcs, precompiledSrcs);
      return this;
    }

    @CanIgnoreReturnValue
    Builder setIntermediateArtifacts(IntermediateArtifacts intermediateArtifacts) {
      Preconditions.checkState(this.intermediateArtifacts == null,
          "intermediateArtifacts is already set to: %s", this.intermediateArtifacts);
      this.intermediateArtifacts = intermediateArtifacts;
      return this;
    }

    CompilationArtifacts build() {
      Optional<Artifact> archive = Optional.absent();
      if (!Iterables.isEmpty(srcs)
          || !Iterables.isEmpty(nonArcSrcs)
          || !Iterables.isEmpty(precompiledSrcs)) {
        archive = Optional.of(intermediateArtifacts.archive());
      }
      return new CompilationArtifacts(
          srcs, nonArcSrcs, additionalHdrs.build(), privateHdrs, archive);
    }
  }

  private final Iterable<Artifact> srcs;
  private final Iterable<Artifact> nonArcSrcs;
  private final Optional<Artifact> archive;
  private final NestedSet<Artifact> additionalHdrs;
  private final Iterable<Artifact> privateHdrs;

  private CompilationArtifacts(
      Iterable<Artifact> srcs,
      Iterable<Artifact> nonArcSrcs,
      NestedSet<Artifact> additionalHdrs,
      Iterable<Artifact> privateHdrs,
      Optional<Artifact> archive) {
    this.srcs = Preconditions.checkNotNull(srcs);
    this.nonArcSrcs = Preconditions.checkNotNull(nonArcSrcs);
    this.additionalHdrs = Preconditions.checkNotNull(additionalHdrs);
    this.privateHdrs = Preconditions.checkNotNull(privateHdrs);
    this.archive = Preconditions.checkNotNull(archive);
  }

  Iterable<Artifact> getSrcs() {
    return srcs;
  }

  @StarlarkMethod(name = "srcs", documented = false, structField = true)
  public Sequence<Artifact> getSrcsForStarlark() {
    return StarlarkList.immutableCopyOf(getSrcs());
  }

  Iterable<Artifact> getNonArcSrcs() {
    return nonArcSrcs;
  }

  @StarlarkMethod(name = "non_arc_srcs", documented = false, structField = true)
  public Sequence<Artifact> getNonArcSrcsForStarlark() {
    return StarlarkList.immutableCopyOf(getNonArcSrcs());
  }

  /** Returns the public headers that aren't included in the hdrs attribute. */
  NestedSet<Artifact> getAdditionalHdrs() {
    return additionalHdrs;
  }

  @StarlarkMethod(name = "additional_hdrs", documented = false, structField = true)
  public Depset getAdditionalHdrsForStarlark() {
    return Depset.of(Artifact.TYPE, getAdditionalHdrs());
  }

  /**
   * Returns the private headers from the srcs attribute, which may by imported by any source or
   * header in this target, but not by sources or headers of dependers.
   */
  Iterable<Artifact> getPrivateHdrs() {
    return privateHdrs;
  }

  @StarlarkMethod(name = "private_hdrs", documented = false, structField = true)
  public Sequence<Artifact> getPrivateHdrsForStarlark() {
    return StarlarkList.immutableCopyOf(getPrivateHdrs());
  }

  /**
   * Returns the output archive library (.a) file created by combining object files of the srcs, non
   * arc srcs, and precompiled srcs of this artifact collection. Returns absent if there are no such
   * source files for which to create an archive library.
   */
  Optional<Artifact> getArchive() {
    return archive;
  }

  @StarlarkMethod(name = "archive", documented = false, allowReturnNones = true, structField = true)
  @Nullable
  public Artifact getArchiveForStarlark() {
    return archive.orNull();
  }
}
