// 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.analysis;

import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.AbstractAction;
import com.google.devtools.build.lib.actions.ActionContext;
import com.google.devtools.build.lib.actions.ActionOwner;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.util.OptionsUtils;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDocumentationCategory;
import com.google.devtools.common.options.OptionEffectTag;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsProvider;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * An action writing the workspace status files.
 *
 * <p>These files represent information about the environment the build was run in. They are used
 * by language-specific build info factories to make the data in them available for individual
 * languages (e.g. by turning them into .h files for C++)
 *
 * <p>The format of these files a list of key-value pairs, one for each line. The key and the value
 * are separated by a space.
 *
 * <p>There are two of these files: volatile and stable. Changes in the volatile file do not
 * cause rebuilds if no other file is changed. This is useful for frequently-changing information
 * that does not significantly affect the build, e.g. the current time.
 */
public abstract class WorkspaceStatusAction extends AbstractAction {

  /** Options controlling the workspace status command. */
  public static class Options extends OptionsBase {
    @Option(
      name = "embed_label",
      defaultValue = "",
      valueHelp = "<string>",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "Embed source control revision or release label in binary"
    )
    public String embedLabel;

    @Option(
      name = "workspace_status_command",
      defaultValue = "",
      converter = OptionsUtils.PathFragmentConverter.class,
      valueHelp = "<path>",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help =
          "A command invoked at the beginning of the build to provide status "
              + "information about the workspace in the form of key/value pairs.  "
              + "See the User's Manual for the full specification."
    )
    public PathFragment workspaceStatusCommand;
  }

  /**
   * The type of a workspace status action key.
   */
  public enum KeyType {
    INTEGER,
    STRING,
  }

  /**
   * Action context required by the workspace status action as well as language-specific actions
   * that write workspace status artifacts.
   */
  public interface Context extends ActionContext {
    ImmutableMap<String, Key> getStableKeys();
    ImmutableMap<String, Key> getVolatileKeys();

    // TODO(ulfjack): Maybe move these to a separate ActionContext interface?
    WorkspaceStatusAction.Options getOptions();

    ImmutableMap<String, String> getClientEnv();

    com.google.devtools.build.lib.shell.Command getCommand();
  }

  /**
   * A key in the workspace status info file.
   */
  public static class Key {
    private final KeyType type;

    private final String defaultValue;
    private final String redactedValue;

    private Key(KeyType type, String defaultValue, String redactedValue) {
      this.type = type;
      this.defaultValue = defaultValue;
      this.redactedValue = redactedValue;
    }

    public KeyType getType() {
      return type;
    }

    public String getDefaultValue() {
      return defaultValue;
    }

    public String getRedactedValue() {
      return redactedValue;
    }

    public static Key of(KeyType type, String defaultValue, String redactedValue) {
      return new Key(type, defaultValue, redactedValue);
    }
  }

  /**
   * Parses the output of the workspace status action.
   *
   * <p>The output is a text file with each line representing a workspace status info key.
   * The key is the part of the line before the first space and should consist of the characters
   * [A-Z_] (although this is not checked). Everything after the first space is the value.
   */
  public static Map<String, String> parseValues(Path file) throws IOException {
    HashMap<String, String> result = new HashMap<>();
    Splitter lineSplitter = Splitter.on(' ').limit(2);
    for (String line :
        Splitter.on('\n').split(new String(FileSystemUtils.readContentAsLatin1(file)))) {
      List<String> items = lineSplitter.splitToList(line);
      if (items.size() != 2) {
        continue;
      }

      result.put(items.get(0), items.get(1));
    }

    return ImmutableMap.copyOf(result);
  }

  /** Environment for the {@link Factory} to create the workspace status action. */
  public interface Environment {
    Artifact createStableArtifact(String name);

    Artifact createVolatileArtifact(String name);
  }

  /**
   * Environment for the {@link Factory} to create the dummy workspace status information. This is a
   * subset of the information provided by CommandEnvironment. However, we cannot reference the
   * CommandEnvironment from here due to layering.
   */
  public interface DummyEnvironment {
    Path getWorkspace();

    String getBuildRequestId();

    OptionsProvider getOptions();
  }

  /**
   * Factory for {@link WorkspaceStatusAction}.
   */
  public interface Factory {
    /**
     * Creates the workspace status action.
     *
     * <p>The action is never re-created, but the same action object is executed on every build. Use
     * {@link Context} to access any non-hermetic data.
     */
    WorkspaceStatusAction createWorkspaceStatusAction(Environment env);

    /**
     * Creates a dummy workspace status map. Used in cases where the build failed, so that part of
     * the workspace status is nevertheless available.
     */
    Map<String, String> createDummyWorkspaceStatus(DummyEnvironment env);
  }

  protected WorkspaceStatusAction(ActionOwner owner,
      Iterable<Artifact> inputs,
      Iterable<Artifact> outputs) {
    super(owner, inputs, outputs);
  }

  /**
   * The volatile status artifact containing items that may change even if nothing changed
   * between the two builds, e.g. current time.
   */
  public abstract Artifact getVolatileStatus();

  /**
   * The stable status artifact containing items that change only if information relevant to the
   * build changes, e.g. the name of the user running the build or the hostname.
   */
  public abstract Artifact getStableStatus();
}
