// 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 static java.nio.charset.StandardCharsets.ISO_8859_1;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.ActionExecutionContext;
import com.google.devtools.build.lib.actions.ActionOwner;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.actions.AbstractFileWriteAction;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.util.Fingerprint;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;

/**
 * Action to create a manifest of input files for processing by a subsequent
 * build step (e.g. runfiles symlinking or archive building).
 *
 * <p>The manifest's format is specifiable by {@link ManifestType}, in
 * accordance with the needs of the calling functionality.
 *
 * <p>Note that this action carefully avoids building the manifest content in
 * memory.
 */
@Immutable // if all ManifestWriter implementations are immutable
public final class SourceManifestAction extends AbstractFileWriteAction {

  private static final String GUID = "07459553-a3d0-4d37-9d78-18ed942470f4";

  /**
   * Interface for defining manifest formatting and reporting specifics. Implementations must be
   * immutable.
   */
  @VisibleForTesting
  interface ManifestWriter {

    /**
     * Writes a single line of manifest output.
     *
     * @param manifestWriter the output stream
     * @param rootRelativePath path of an entry relative to the manifest's root
     * @param symlink (optional) symlink that resolves the above path
     */
    void writeEntry(Writer manifestWriter, PathFragment rootRelativePath,
        @Nullable Artifact symlink) throws IOException;

    /**
     * Fulfills {@link com.google.devtools.build.lib.actions.AbstractAction#getMnemonic()}
     */
    String getMnemonic();

    /**
     * Fulfills {@link com.google.devtools.build.lib.actions.AbstractAction#getRawProgressMessage()}
     */
    String getRawProgressMessage();
  }

  /**
   * The strategy we use to write manifest entries.
   */
  private final ManifestWriter manifestWriter;

  /**
   * The runfiles for which to create the symlink tree.
   */
  private final Runfiles runfiles;

  /**
   * Creates a new AbstractSourceManifestAction instance using latin1 encoding
   * to write the manifest file and with a specified root path for manifest entries.
   *
   * @param manifestWriter the strategy to use to write manifest entries
   * @param owner the action owner
   * @param output the file to which to write the manifest
   * @param runfiles runfiles
   */
  private SourceManifestAction(ManifestWriter manifestWriter, ActionOwner owner, Artifact output,
      Runfiles runfiles) {
    super(owner, getDependencies(runfiles), output, false);
    this.manifestWriter = manifestWriter;
    this.runfiles = runfiles;
  }

  /** The {@link Runfiles} for which this action creates the symlink tree. */
  public Runfiles getGeneratedRunfiles() {
    return runfiles;
  }

  @VisibleForTesting
  public void writeOutputFile(OutputStream out, EventHandler eventHandler)
      throws IOException {
    writeFile(out, runfiles.getRunfilesInputs(eventHandler, getOwner().getLocation()));
  }

  @Override
  public DeterministicWriter newDeterministicWriter(ActionExecutionContext ctx)
      throws IOException {
    final Map<PathFragment, Artifact> runfilesInputs =
        runfiles.getRunfilesInputs(ctx.getEventHandler(), getOwner().getLocation());
    return new DeterministicWriter() {
      @Override
      public void writeOutputFile(OutputStream out) throws IOException {
        writeFile(out, runfilesInputs);
      }
    };
  }

  @Override
  public boolean isRemotable() {
    // There is little gain to remoting these, since they include absolute path names inline.
    return false;
  }

  /**
   * Returns the input dependencies for this action. Note we don't need to create the symlink
   * target Artifacts before we write the output manifest, so this Action does not have to
   * depend on them. The only necessary dependencies are pruning manifests, which must be read
   * to properly prune the tree.
   */
  public static Collection<Artifact> getDependencies(Runfiles runfiles) {
    ImmutableList.Builder<Artifact> builder = ImmutableList.builder();
    for (Runfiles.PruningManifest manifest : runfiles.getPruningManifests()) {
      builder.add(manifest.getManifestFile());
    }
    return builder.build();
  }

  /**
   * Sort the entries in both the normal and root manifests and write the output
   * file.
   *
   * @param out is the message stream to write errors to.
   * @param output The actual mapping of the output manifest.
   * @throws IOException
   */
  private void writeFile(OutputStream out, Map<PathFragment, Artifact> output) throws IOException {
    Writer manifestFile = new BufferedWriter(new OutputStreamWriter(out, ISO_8859_1));

    Comparator<Map.Entry<PathFragment, Artifact>> fragmentComparator =
          new Comparator<Map.Entry<PathFragment, Artifact>>() {
      @Override
      public int compare(Map.Entry<PathFragment, Artifact> path1,
                         Map.Entry<PathFragment, Artifact> path2) {
        return path1.getKey().compareTo(path2.getKey());
      }
    };

    List<Map.Entry<PathFragment, Artifact>> sortedManifest = new ArrayList<>(output.entrySet());
    Collections.sort(sortedManifest, fragmentComparator);

    for (Map.Entry<PathFragment, Artifact> line : sortedManifest) {
      manifestWriter.writeEntry(manifestFile, line.getKey(), line.getValue());
    }

    manifestFile.flush();
  }

  @Override
  public String getMnemonic() {
    return manifestWriter.getMnemonic();
  }

  @Override
  protected String getRawProgressMessage() {
    return manifestWriter.getRawProgressMessage() + " for " + getOwner().getLabel();
  }

  @Override
  protected String computeKey() {
    Fingerprint f = new Fingerprint();
    f.addString(GUID);
    f.addBoolean(runfiles.getLegacyExternalRunfiles());
    f.addPath(runfiles.getSuffix());
    Map<PathFragment, Artifact> symlinks = runfiles.getSymlinksAsMap(null);
    f.addInt(symlinks.size());
    for (Map.Entry<PathFragment, Artifact> symlink : symlinks.entrySet()) {
      f.addPath(symlink.getKey());
      f.addPath(symlink.getValue().getPath());
    }
    Map<PathFragment, Artifact> rootSymlinks = runfiles.getRootSymlinksAsMap(null);
    f.addInt(rootSymlinks.size());
    for (Map.Entry<PathFragment, Artifact> rootSymlink : rootSymlinks.entrySet()) {
      f.addPath(rootSymlink.getKey());
      f.addPath(rootSymlink.getValue().getPath());
    }

    for (Artifact artifact : runfiles.getArtifacts()) {
      f.addPath(artifact.getRootRelativePath());
      f.addPath(artifact.getPath());
    }
    return f.hexDigestAndReset();
  }

  /**
   * Supported manifest writing strategies.
   */
  public enum ManifestType implements ManifestWriter {

    /**
     * Writes each line as:
     *
     * [rootRelativePath] [resolvingSymlink]
     *
     * <p>This strategy is suitable for creating an input manifest to a source view tree. Its
     * output is a valid input to
     * {@link com.google.devtools.build.lib.analysis.actions.SymlinkTreeAction}.
     */
    SOURCE_SYMLINKS {
      @Override
      public void writeEntry(Writer manifestWriter, PathFragment rootRelativePath, Artifact symlink)
          throws IOException {
        manifestWriter.append(rootRelativePath.getPathString());
        // This trailing whitespace is REQUIRED to process the single entry line correctly.
        manifestWriter.append(' ');
        if (symlink != null) {
          manifestWriter.append(symlink.getPath().getPathString());
        }
        manifestWriter.append('\n');
      }

      @Override
      public String getMnemonic() {
        return "SourceSymlinkManifest";
      }

      @Override
      public String getRawProgressMessage() {
        return "Creating source manifest";
      }
    },

    /**
     * Writes each line as:
     *
     * [rootRelativePath]
     *
     * <p>This strategy is suitable for an input into a packaging system (notably .par) that
     * consumes a list of all source files but needs that list to be constant with respect to
     * how the user has their client laid out on local disk.
     */
    SOURCES_ONLY {
      @Override
      public void writeEntry(Writer manifestWriter, PathFragment rootRelativePath, Artifact symlink)
          throws IOException {
        manifestWriter.append(rootRelativePath.getPathString());
        manifestWriter.append('\n');
        manifestWriter.flush();
      }

      @Override
      public String getMnemonic() {
        return "PackagingSourcesManifest";
      }

      @Override
      public String getRawProgressMessage() {
        return "Creating file sources list";
      }
    }
  }

  /** Creates an action for the given runfiles. */
  public static SourceManifestAction forRunfiles(ManifestType manifestType, ActionOwner owner,
      Artifact output, Runfiles runfiles) {
    return new SourceManifestAction(manifestType, owner, output, runfiles);
  }

  /**
   * Builder class to construct {@link SourceManifestAction} instances.
   */
  public static final class Builder {
    private final ManifestWriter manifestWriter;
    private final ActionOwner owner;
    private final Artifact output;
    private final Runfiles.Builder runfilesBuilder;

    public Builder(String prefix, ManifestType manifestType, ActionOwner owner, Artifact output,
                   boolean legacyExternalRunfiles) {
      this.runfilesBuilder = new Runfiles.Builder(prefix, legacyExternalRunfiles);
      manifestWriter = manifestType;
      this.owner = owner;
      this.output = output;
    }

    @VisibleForTesting  // Only used for testing.
    Builder(String prefix, ManifestWriter manifestWriter, ActionOwner owner, Artifact output) {
      this.runfilesBuilder = new Runfiles.Builder(prefix, false);
      this.manifestWriter = manifestWriter;
      this.owner = owner;
      this.output = output;
    }

    public SourceManifestAction build() {
      return new SourceManifestAction(manifestWriter, owner, output, runfilesBuilder.build());
    }

    /**
     * Adds a set of symlinks from the artifacts' root-relative paths to the
     * artifacts themselves.
     */
    public Builder addSymlinks(Iterable<Artifact> artifacts) {
      runfilesBuilder.addArtifacts(artifacts);
      return this;
    }

    /**
     * Adds a map of symlinks.
     */
    public Builder addSymlinks(Map<PathFragment, Artifact> symlinks) {
      runfilesBuilder.addSymlinks(symlinks);
      return this;
    }

    /**
     * Adds a single symlink.
     */
    public Builder addSymlink(PathFragment link, Artifact target) {
      runfilesBuilder.addSymlink(link, target);
      return this;
    }

    /**
     * <p>Adds a mapping of Artifacts to the directory above the normal symlink
     * forest base.
     */
    public Builder addRootSymlinks(Map<PathFragment, Artifact> rootSymlinks) {
      runfilesBuilder.addRootSymlinks(rootSymlinks);
      return this;
    }

    /**
     * Set the empty files supplier for the manifest, see {@link Runfiles.EmptyFilesSupplier}
     * for more details.
     */
    public Builder setEmptyFilesSupplier(Runfiles.EmptyFilesSupplier supplier) {
      runfilesBuilder.setEmptyFilesSupplier(supplier);
      return this;
    }

    /**
     * Adds a runfiles pruning manifest.
     */
    @VisibleForTesting
    Builder addPruningManifest(Runfiles.PruningManifest manifest) {
      runfilesBuilder.addPruningManifest(manifest);
      return this;
    }
  }
}
