// 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.Depset.ElementType;
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 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<SdkFramework> sdkFrameworks = NestedSetBuilder.stableOrder();
    private final NestedSetBuilder<SdkFramework> 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) {
      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.
     */
    public Builder addHdrs(NestedSet<Artifact> hdrs) {
      this.hdrs.addTransitive(hdrs);
      return this;
    }

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

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

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

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

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

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

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

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

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

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

    /**
     * Sets the package path from which to base the header search paths.
     */
    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.
     */
    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<SdkFramework> frameworks = NestedSetBuilder.stableOrder();
        for (String explicit : ruleContext.attributes().get("sdk_frameworks", Type.STRING_LIST)) {
          frameworks.add(new SdkFramework(explicit));
        }
        builder.addSdkFrameworks(frameworks.build());
      }

      if (ruleContext.attributes().has("weak_sdk_frameworks", Type.STRING_LIST)) {
        NestedSetBuilder<SdkFramework> weakFrameworks = NestedSetBuilder.stableOrder();
        for (String frameworkName :
            ruleContext.attributes().get("weak_sdk_frameworks", Type.STRING_LIST)) {
          weakFrameworks.add(new SdkFramework(frameworkName));
        }
        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) {
      addCompileOptionsFromRuleContext(builder, ruleContext, /* copts= */ null);
    }

    static void addCompileOptionsFromRuleContext(
        Builder builder, RuleContext ruleContext, Iterable<String> copts) {
      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<SdkFramework> sdkFrameworks;
  private final NestedSet<SdkFramework> 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<SdkFramework> sdkFrameworks,
      NestedSet<SdkFramework> 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.TYPE, hdrs());
  }

  @StarlarkMethod(name = "textual_hdrs", documented = false, structField = true)
  public Depset textualHdrsForStarlark() {
    return Depset.of(Artifact.TYPE, 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(
        ElementType.STRING,
        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(
        ElementType.STRING,
        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<SdkFramework> sdkFrameworks() {
    return this.sdkFrameworks;
  }

  @StarlarkMethod(name = "sdk_frameworks", documented = false, structField = true)
  public Depset sdkFrameworksForStarlark() {
    return (Depset)
        ObjcProviderStarlarkConverters.convertToStarlark(
            ObjcProvider.SDK_FRAMEWORK, sdkFrameworks());
  }

  @StarlarkMethod(name = "weak_sdk_frameworks", documented = false, structField = true)
  public Depset weakSdkFrameworksForStarlark() {
    return (Depset)
        ObjcProviderStarlarkConverters.convertToStarlark(
            ObjcProvider.SDK_FRAMEWORK, weakSdkFrameworks());
  }

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

  @StarlarkMethod(name = "sdk_dylibs", documented = false, structField = true)
  public Depset sdkDylibsForStarlark() {
    return Depset.of(ElementType.STRING, 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(
        ElementType.STRING,
        NestedSetBuilder.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;
  }
}
