// Copyright 2016 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.analysis.PrerequisiteArtifacts;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.cmdline.Label;
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.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.rules.cpp.CcCommon;
import com.google.devtools.build.lib.rules.cpp.CppHelper;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import net.starlark.java.annot.Param;
import net.starlark.java.annot.StarlarkMethod;
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.StarlarkList;
import net.starlark.java.eval.StarlarkValue;

/** Provides a way to access attributes that are common to all compilation rules. */
// TODO(bazel-team): Delete and move into support-specific attributes classes once ObjcCommon is
// gone.
final class CompilationAttributes implements StarlarkValue {
  static class Builder {
    private final NestedSetBuilder<Artifact> hdrs = NestedSetBuilder.stableOrder();
    private final NestedSetBuilder<Artifact> textualHdrs = NestedSetBuilder.stableOrder();
    private final NestedSetBuilder<PathFragment> includes = NestedSetBuilder.stableOrder();
    private final NestedSetBuilder<PathFragment> sdkIncludes = NestedSetBuilder.stableOrder();
    private final ImmutableList.Builder<String> copts = ImmutableList.builder();
    private final ImmutableList.Builder<String> linkopts = ImmutableList.builder();
    private final ImmutableList.Builder<Artifact> linkInputs = ImmutableList.builder();
    private final ImmutableList.Builder<String> defines = ImmutableList.builder();
    private final NestedSetBuilder<String> sdkFrameworks = NestedSetBuilder.stableOrder();
    private final NestedSetBuilder<String> weakSdkFrameworks = NestedSetBuilder.stableOrder();
    private final NestedSetBuilder<String> sdkDylibs = NestedSetBuilder.stableOrder();
    private Optional<PathFragment> packageFragment = Optional.absent();
    private boolean enableModules;

    /** Adds the default values available through the rule's context. */
    static Builder fromRuleContext(RuleContext ruleContext) throws InterruptedException {
      Builder builder = new Builder();

      addHeadersFromRuleContext(builder, ruleContext);
      addIncludesFromRuleContext(builder, ruleContext);
      addSdkAttributesFromRuleContext(builder, ruleContext);
      addCompileOptionsFromRuleContext(builder, ruleContext);
      addModuleOptionsFromRuleContext(builder, ruleContext);

      return builder;
    }

    /** Adds headers to be made available for dependents. */
    @CanIgnoreReturnValue
    public Builder addHdrs(NestedSet<Artifact> hdrs) {
      this.hdrs.addTransitive(hdrs);
      return this;
    }

    /** Adds headers that cannot be compiled individually. */
    @CanIgnoreReturnValue
    public Builder addTextualHdrs(NestedSet<Artifact> textualHdrs) {
      this.textualHdrs.addTransitive(textualHdrs);
      return this;
    }

    /** Adds include paths to be made available for compilation. */
    @CanIgnoreReturnValue
    public Builder addIncludes(NestedSet<PathFragment> includes) {
      this.includes.addTransitive(includes);
      return this;
    }

    /** Adds paths for SDK includes. */
    @CanIgnoreReturnValue
    public Builder addSdkIncludes(NestedSet<PathFragment> sdkIncludes) {
      this.sdkIncludes.addTransitive(sdkIncludes);
      return this;
    }

    /** Adds compile-time options. */
    @CanIgnoreReturnValue
    public Builder addCopts(Iterable<String> copts) {
      this.copts.addAll(copts);
      return this;
    }

    /** Adds link-time options. */
    @CanIgnoreReturnValue
    public Builder addLinkopts(Iterable<String> linkopts) {
      this.linkopts.addAll(linkopts);
      return this;
    }

    /** Adds additional linker inputs. */
    @CanIgnoreReturnValue
    public Builder addLinkInputs(Iterable<Artifact> linkInputs) {
      this.linkInputs.addAll(linkInputs);
      return this;
    }

    /** Adds defines. */
    @CanIgnoreReturnValue
    public Builder addDefines(Iterable<String> defines) {
      this.defines.addAll(defines);
      return this;
    }

    /** Adds SDK frameworks to link against. */
    @CanIgnoreReturnValue
    public Builder addSdkFrameworks(NestedSet<String> sdkFrameworks) {
      this.sdkFrameworks.addTransitive(sdkFrameworks);
      return this;
    }

    /** Adds SDK frameworks to be linked weakly. */
    @CanIgnoreReturnValue
    public Builder addWeakSdkFrameworks(NestedSet<String> weakSdkFrameworks) {
      this.weakSdkFrameworks.addTransitive(weakSdkFrameworks);
      return this;
    }

    /** Adds SDK Dylibs to link against. */
    @CanIgnoreReturnValue
    public Builder addSdkDylibs(NestedSet<String> sdkDylibs) {
      this.sdkDylibs.addTransitive(sdkDylibs);
      return this;
    }

    /** Sets the package path from which to base the header search paths. */
    @CanIgnoreReturnValue
    public Builder setPackageFragment(PathFragment packageFragment) {
      Preconditions.checkState(
          !this.packageFragment.isPresent(),
          "packageFragment is already set to %s",
          this.packageFragment);
      this.packageFragment = Optional.of(packageFragment);
      return this;
    }

    /** Enables the usage of clang modules maps during compilation. */
    @CanIgnoreReturnValue
    public Builder enableModules() {
      this.enableModules = true;
      return this;
    }

    /**
     * Builds a {@code CompilationAttributes} object.
     */
    public CompilationAttributes build() {
      return new CompilationAttributes(
          this.hdrs.build(),
          this.textualHdrs.build(),
          this.includes.build(),
          this.sdkIncludes.build(),
          this.sdkFrameworks.build(),
          this.weakSdkFrameworks.build(),
          this.sdkDylibs.build(),
          this.packageFragment,
          this.copts.build(),
          this.linkopts.build(),
          this.linkInputs.build(),
          this.defines.build(),
          this.enableModules);
    }

    static void addHeadersFromRuleContext(Builder builder, RuleContext ruleContext) {
      if (ruleContext.attributes().has("hdrs", BuildType.LABEL_LIST)) {
        NestedSetBuilder<Artifact> headers = NestedSetBuilder.stableOrder();
        for (Pair<Artifact, Label> header : CcCommon.getHeaders(ruleContext)) {
          headers.add(header.first);
        }
        builder.addHdrs(headers.build());
      }

      if (ruleContext.attributes().has("textual_hdrs", BuildType.LABEL_LIST)) {
        builder.addTextualHdrs(PrerequisiteArtifacts.nestedSet(ruleContext, "textual_hdrs"));
      }
    }

    static void addIncludesFromRuleContext(Builder builder, RuleContext ruleContext) {
      if (ruleContext.attributes().has("includes", Type.STRING_LIST)) {
        NestedSetBuilder<PathFragment> includes = NestedSetBuilder.stableOrder();
        includes.addAll(
            Iterables.transform(
                ruleContext.attributes().get("includes", Type.STRING_LIST), PathFragment::create));
        builder.addIncludes(includes.build());
      }

      if (ruleContext.attributes().has("sdk_includes", Type.STRING_LIST)) {
        NestedSetBuilder<PathFragment> sdkIncludes = NestedSetBuilder.stableOrder();
        sdkIncludes.addAll(
            Iterables.transform(
                ruleContext.attributes().get("sdk_includes", Type.STRING_LIST),
                PathFragment::create));
        builder.addSdkIncludes(sdkIncludes.build());
      }
    }

    static void addSdkAttributesFromRuleContext(Builder builder, RuleContext ruleContext) {
      if (ruleContext.attributes().has("sdk_frameworks", Type.STRING_LIST)) {
        NestedSetBuilder<String> frameworks = NestedSetBuilder.stableOrder();
        for (String explicit : ruleContext.attributes().get("sdk_frameworks", Type.STRING_LIST)) {
          frameworks.add(explicit);
        }
        if (ruleContext.getFragment(ObjcConfiguration.class).disallowSdkFrameworksAttributes()
            && !frameworks.isEmpty()) {
          ruleContext.attributeError(
              "sdk_frameworks",
              "sdk_frameworks attribute is disallowed. Use explicit dependencies instead.");
        }
        builder.addSdkFrameworks(frameworks.build());
      }

      if (ruleContext.attributes().has("weak_sdk_frameworks", Type.STRING_LIST)) {
        NestedSetBuilder<String> weakFrameworks = NestedSetBuilder.stableOrder();
        for (String frameworkName :
            ruleContext.attributes().get("weak_sdk_frameworks", Type.STRING_LIST)) {
          weakFrameworks.add(frameworkName);
        }
        if (ruleContext.getFragment(ObjcConfiguration.class).disallowSdkFrameworksAttributes()
            && !weakFrameworks.isEmpty()) {
          ruleContext.attributeError(
              "weak_sdk_frameworks",
              "weak_sdk_frameworks attribute is disallowed.  Use explicit dependencies instead.");
        }
        builder.addWeakSdkFrameworks(weakFrameworks.build());
      }

      if (ruleContext.attributes().has("sdk_dylibs", Type.STRING_LIST)) {
        NestedSetBuilder<String> sdkDylibs = NestedSetBuilder.stableOrder();
        sdkDylibs.addAll(ruleContext.attributes().get("sdk_dylibs", Type.STRING_LIST));
        builder.addSdkDylibs(sdkDylibs.build());
      }
    }

    private static void addCompileOptionsFromRuleContext(Builder builder, RuleContext ruleContext)
        throws InterruptedException {
      addCompileOptionsFromRuleContext(builder, ruleContext, /* copts= */ null);
    }

    static void addCompileOptionsFromRuleContext(
        Builder builder, RuleContext ruleContext, Iterable<String> copts)
        throws InterruptedException {
      if (ruleContext.attributes().has("copts", Type.STRING_LIST)) {
        if (copts == null) {
          builder.addCopts(ruleContext.getExpander().withDataLocations().tokenized("copts"));
        } else {
          builder.addCopts(copts);
        }
      }

      if (ruleContext.attributes().has("linkopts", Type.STRING_LIST)) {
        builder.addLinkopts(CppHelper.getLinkopts(ruleContext));
      }

      if (ruleContext.attributes().has("additional_linker_inputs", BuildType.LABEL_LIST)) {
        builder.addLinkInputs(
            ruleContext.getPrerequisiteArtifacts("additional_linker_inputs").list());
      }

      if (ruleContext.attributes().has("defines", Type.STRING_LIST)) {
        builder.addDefines(ruleContext.getExpander().withDataLocations().tokenized("defines"));
      }
    }

    protected static void addModuleOptionsFromRuleContext(
        Builder builder, RuleContext ruleContext) {
      PathFragment packageFragment = ruleContext.getPackageDirectory();
      if (packageFragment != null) {
        builder.setPackageFragment(packageFragment);
      }

      if (ruleContext.attributes().has("enable_modules", Type.BOOLEAN)
          && ruleContext.attributes().get("enable_modules", Type.BOOLEAN)) {
        builder.enableModules();
      }
    }
  }

  private final NestedSet<Artifact> hdrs;
  private final NestedSet<Artifact> textualHdrs;
  private final NestedSet<PathFragment> includes;
  private final NestedSet<PathFragment> sdkIncludes;
  private final NestedSet<String> sdkFrameworks;
  private final NestedSet<String> weakSdkFrameworks;
  private final NestedSet<String> sdkDylibs;
  private final Optional<PathFragment> packageFragment;
  private final ImmutableList<String> copts;
  private final ImmutableList<String> linkopts;
  private final ImmutableList<Artifact> linkInputs;
  private final ImmutableList<String> defines;
  private final boolean enableModules;

  private CompilationAttributes(
      NestedSet<Artifact> hdrs,
      NestedSet<Artifact> textualHdrs,
      NestedSet<PathFragment> includes,
      NestedSet<PathFragment> sdkIncludes,
      NestedSet<String> sdkFrameworks,
      NestedSet<String> weakSdkFrameworks,
      NestedSet<String> sdkDylibs,
      Optional<PathFragment> packageFragment,
      ImmutableList<String> copts,
      ImmutableList<String> linkopts,
      ImmutableList<Artifact> linkInputs,
      ImmutableList<String> defines,
      boolean enableModules) {
    this.hdrs = hdrs;
    this.textualHdrs = textualHdrs;
    this.includes = includes;
    this.sdkIncludes = sdkIncludes;
    this.sdkFrameworks = sdkFrameworks;
    this.weakSdkFrameworks = weakSdkFrameworks;
    this.sdkDylibs = sdkDylibs;
    this.packageFragment = packageFragment;
    this.copts = copts;
    this.linkopts = linkopts;
    this.linkInputs = linkInputs;
    this.defines = defines;
    this.enableModules = enableModules;
  }

  /**
   * Returns the headers to be made available for dependents.
   */
  public NestedSet<Artifact> hdrs() {
    return this.hdrs;
  }

  @StarlarkMethod(name = "hdrs", documented = false, structField = true)
  public Depset hdrsForStarlark() {
    return Depset.of(Artifact.class, hdrs());
  }

  @StarlarkMethod(name = "textual_hdrs", documented = false, structField = true)
  public Depset textualHdrsForStarlark() {
    return Depset.of(Artifact.class, textualHdrs());
  }

  /**
   * Returns the headers that cannot be compiled individually.
   */
  public NestedSet<Artifact> textualHdrs() {
    return this.textualHdrs;
  }

  /**
   * Returns the include paths to be made available for compilation.
   */
  public NestedSet<PathFragment> includes() {
    return this.includes;
  }

  @StarlarkMethod(name = "includes", documented = false, structField = true)
  public Depset includesForStarlark() {
    return Depset.of(
        String.class,
        NestedSetBuilder.wrap(
            Order.COMPILE_ORDER,
            includes().toList().stream()
                .map(PathFragment::getSafePathString)
                .collect(ImmutableList.toImmutableList())));
  }

  @StarlarkMethod(name = "sdk_includes", documented = false, structField = true)
  public Depset sdkIncludesForStarlark() {
    return Depset.of(
        String.class,
        NestedSetBuilder.wrap(
            Order.COMPILE_ORDER,
            sdkIncludes().toList().stream()
                .map(PathFragment::getSafePathString)
                .collect(ImmutableList.toImmutableList())));
  }

  /**
   * Returns the paths for SDK includes.
   */
  public NestedSet<PathFragment> sdkIncludes() {
    return this.sdkIncludes;
  }

  /** Returns the SDK frameworks to link against. */
  public NestedSet<String> sdkFrameworks() {
    return this.sdkFrameworks;
  }

  @StarlarkMethod(name = "sdk_frameworks", documented = false, structField = true)
  public Depset sdkFrameworksForStarlark() {
    return Depset.of(String.class, sdkFrameworks);
  }

  @StarlarkMethod(name = "weak_sdk_frameworks", documented = false, structField = true)
  public Depset weakSdkFrameworksForStarlark() {
    return Depset.of(String.class, weakSdkFrameworks);
  }

  /** Returns the SDK frameworks to be linked weakly. */
  public NestedSet<String> weakSdkFrameworks() {
    return this.weakSdkFrameworks;
  }

  @StarlarkMethod(name = "sdk_dylibs", documented = false, structField = true)
  public Depset sdkDylibsForStarlark() {
    return Depset.of(String.class, sdkDylibs);
  }

  /**
   * Returns the SDK Dylibs to link against.
   */
  public NestedSet<String> sdkDylibs() {
    return this.sdkDylibs;
  }

  @StarlarkMethod(
      name = "header_search_paths",
      documented = false,
      parameters = {
        @Param(name = "genfiles_dir", positional = false, named = true),
      })
  public Depset headerSearchPathsForStarlark(String genfilesDir) {
    return Depset.of(
        String.class,
        NestedSetBuilder.<String>stableOrder()
            .addAll(
                headerSearchPaths(PathFragment.create(genfilesDir)).toList().stream()
                    .map(PathFragment::toString)
                    .collect(ImmutableList.toImmutableList()))
            .build());
  }

  /**
   * Returns the exec paths of all header search paths that should be added to this target and
   * dependers on this target, obtained from the {@code includes} attribute.
   */
  public NestedSet<PathFragment> headerSearchPaths(PathFragment genfilesFragment) {
    NestedSetBuilder<PathFragment> paths = NestedSetBuilder.stableOrder();
    if (packageFragment.isPresent()) {
      PathFragment packageFrag = packageFragment.get();
      PathFragment genfilesFrag = genfilesFragment.getRelative(packageFrag);
      for (PathFragment include : includes().toList()) {
        if (!include.isAbsolute()) {
          paths.add(packageFrag.getRelative(include));
          paths.add(genfilesFrag.getRelative(include));
        }
      }
    }
    return paths.build();
  }

  /**
   * Returns the compile-time options.
   */
  public ImmutableList<String> copts() {
    return this.copts;
  }

  @StarlarkMethod(name = "copts", documented = false, structField = true)
  public Sequence<String> getCoptsForStarlark() {
    return StarlarkList.immutableCopyOf(copts());
  }

  /**
   * Returns the link-time options.
   */
  public ImmutableList<String> linkopts() {
    return this.linkopts;
  }

  /** Returns the additional link inputs. */
  public ImmutableList<Artifact> linkInputs() {
    return this.linkInputs;
  }

  @StarlarkMethod(name = "defines", documented = false, structField = true)
  public Sequence<String> getDefinesForStarlark() {
    return StarlarkList.immutableCopyOf(defines());
  }

  /** Returns the defines. */
  public ImmutableList<String> defines() {
    return this.defines;
  }

  /**
   * Returns whether this target uses language features that require clang modules, such as
   * {@literal @}import.
   */
  @StarlarkMethod(name = "enable_modules", documented = false, structField = true)
  public boolean enableModules() {
    return this.enableModules;
  }
}
