// Copyright 2017 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.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.rules.cpp.CcCommon.CoptsFilter;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.CppCompileAction.DotdFile;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
import com.google.devtools.build.lib.util.Pair;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;

/** The compile command line for the C++ compile action. */
@AutoCodec
public final class CompileCommandLine {
  private final Artifact sourceFile;
  private final CoptsFilter coptsFilter;
  private final FeatureConfiguration featureConfiguration;
  private final CcToolchainVariables variables;
  private final String actionName;
  private final DotdFile dotdFile;

  @AutoCodec.Instantiator
  @VisibleForSerialization
  CompileCommandLine(
      Artifact sourceFile,
      CoptsFilter coptsFilter,
      FeatureConfiguration featureConfiguration,
      CcToolchainVariables variables,
      String actionName,
      DotdFile dotdFile) {
    this.sourceFile = Preconditions.checkNotNull(sourceFile);
    this.coptsFilter = coptsFilter;
    this.featureConfiguration = Preconditions.checkNotNull(featureConfiguration);
    this.variables = variables;
    this.actionName = actionName;
    this.dotdFile = isGenerateDotdFile(sourceFile) ? dotdFile : null;
  }

  /** Returns true if Dotd file should be generated. */
  private boolean isGenerateDotdFile(Artifact sourceArtifact) {
    return CppFileTypes.headerDiscoveryRequired(sourceArtifact)
        && !featureConfiguration.isEnabled(CppRuleClasses.PARSE_SHOWINCLUDES);
  }

  /** Returns the environment variables that should be set for C++ compile actions. */
  protected Map<String, String> getEnvironment() {
    return featureConfiguration.getEnvironmentVariables(actionName, variables);
  }

  /** Returns the tool path for the compilation based on the current feature configuration. */
  @VisibleForTesting
  public String getToolPath() {
    Preconditions.checkArgument(
        featureConfiguration.actionIsConfigured(actionName),
        "Expected action_config for '%s' to be configured",
        actionName);
    return featureConfiguration.getToolPathForAction(actionName);
  }

  /**
   * @param overwrittenVariables: Variables that will overwrite original build variables. When null,
   *     unmodified original variables are used.
   */
  protected List<String> getArguments(@Nullable CcToolchainVariables overwrittenVariables) {
    List<String> commandLine = new ArrayList<>();

    // first: The command name.
    commandLine.add(getToolPath());

    // second: The compiler options.
    commandLine.addAll(getCompilerOptions(overwrittenVariables));
    return commandLine;
  }

  public List<String> getCompilerOptions(@Nullable CcToolchainVariables overwrittenVariables) {
    List<String> options = new ArrayList<>();

    CcToolchainVariables updatedVariables = variables;
    if (variables != null && overwrittenVariables != null) {
      CcToolchainVariables.Builder variablesBuilder = new CcToolchainVariables.Builder(variables);
      variablesBuilder.addAllNonTransitive(overwrittenVariables);
      updatedVariables = variablesBuilder.build();
    }
    addFilteredOptions(
        options, featureConfiguration.getPerFeatureExpansions(actionName, updatedVariables));

    return options;
  }

  // For each option in 'in', add it to 'out' unless it is matched by the 'coptsFilter' regexp.
  private void addFilteredOptions(
      List<String> out, List<Pair<String, List<String>>> expandedFeatures) {
    for (Pair<String, List<String>> pair : expandedFeatures) {
      if (pair.getFirst().equals(CppRuleClasses.UNFILTERED_COMPILE_FLAGS_FEATURE_NAME)) {
        out.addAll(pair.getSecond());
        continue;
      }
      // We do not uses Java's stream API here as it causes a substantial overhead compared to the
      // very little work that this is actually doing.
      for (String flag : pair.getSecond()) {
        if (coptsFilter.passesFilter(flag)) {
          out.add(flag);
        }
      }
    }
  }

  public Artifact getSourceFile() {
    return sourceFile;
  }

  public DotdFile getDotdFile() {
    return dotdFile;
  }

  public CcToolchainVariables getVariables() {
    return variables;
  }

  /**
   * Returns all user provided copts flags.
   *
   * TODO(b/64108724): Get rid of this method when we don't need to parse copts to collect include
   * directories anymore (meaning there is a way of specifying include directories using an
   * explicit attribute, not using platform-dependent garbage bag that copts is).
   */
  public ImmutableList<String> getCopts() {
    if (variables.isAvailable(CompileBuildVariables.USER_COMPILE_FLAGS.getVariableName())) {
      return CcToolchainVariables.toStringList(
          variables, CompileBuildVariables.USER_COMPILE_FLAGS.getVariableName());
    } else {
      return ImmutableList.of();
    }
  }

  public static Builder builder(
      Artifact sourceFile,
      CoptsFilter coptsFilter,
      String actionName,
      DotdFile dotdFile) {
    return new Builder(sourceFile, coptsFilter, actionName, dotdFile);
  }

  /** A builder for a {@link CompileCommandLine}. */
  public static final class Builder {
    private final Artifact sourceFile;
    private CoptsFilter coptsFilter;
    private FeatureConfiguration featureConfiguration;
    private CcToolchainVariables variables = CcToolchainVariables.EMPTY;
    private final String actionName;
    @Nullable private final DotdFile dotdFile;

    public CompileCommandLine build() {
      return new CompileCommandLine(
          Preconditions.checkNotNull(sourceFile),
          Preconditions.checkNotNull(coptsFilter),
          Preconditions.checkNotNull(featureConfiguration),
          Preconditions.checkNotNull(variables),
          Preconditions.checkNotNull(actionName),
          dotdFile);
    }

    private Builder(
        Artifact sourceFile,
        CoptsFilter coptsFilter,
        String actionName,
        DotdFile dotdFile) {
      this.sourceFile = sourceFile;
      this.coptsFilter = coptsFilter;
      this.actionName = actionName;
      this.dotdFile = dotdFile;
    }

    /** Sets the feature configuration for this compile action. */
    public Builder setFeatureConfiguration(FeatureConfiguration featureConfiguration) {
      this.featureConfiguration = featureConfiguration;
      return this;
    }

    public Builder setVariables(CcToolchainVariables variables) {
      this.variables = variables;
      return this;
    }

    @VisibleForTesting
    Builder setCoptsFilter(CoptsFilter filter) {
      this.coptsFilter = Preconditions.checkNotNull(filter);
      return this;
    }
  }
}
