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

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.io.LineProcessor;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.AnalysisUtils;
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 java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Representation of a Fileset manifest.
 */
public final class FilesetManifest {
  /**
   * Mode that determines how to handle relative target paths.
   */
  public enum RelativeSymlinkBehavior {
    /** Ignore any relative target paths. */
    IGNORE,

    /** Give an error if a relative target path is encountered. */
    ERROR,

    /**
     * Attempt to locally resolve the relative target path. Consider a manifest with two entries,
     * foo points to bar, and bar points to the absolute path /foobar. In that case, we can
     * determine that foo actually points at /foobar. Throw an exception if the local resolution
     * fails, e.g., if the target is not in the current manifest, or if it points at another
     * symlink (we could theoretically resolve recursively, but that's more complexity).
     */
    RESOLVE;
  }

  public static FilesetManifest parseManifestFile(
      Artifact manifest,
      Path execRoot,
      String workspaceName,
      RelativeSymlinkBehavior relSymlinkBehavior)
          throws IOException {
    return parseManifestFile(
        manifest.getExecPath(),
        execRoot,
        workspaceName,
        relSymlinkBehavior);
  }

  public static FilesetManifest parseManifestFile(
      PathFragment manifest,
      Path execRoot,
      String workspaceName,
      RelativeSymlinkBehavior relSymlinkBehavior)
          throws IOException {
    Path file = execRoot.getRelative(AnalysisUtils.getManifestPathFromFilesetPath(manifest));
    try {
      return FileSystemUtils.asByteSource(file).asCharSource(UTF_8)
          .readLines(
              new ManifestLineProcessor(workspaceName, manifest, relSymlinkBehavior));
    } catch (IllegalStateException e) {
      // We can't throw IOException from getResult below, so we instead use an unchecked exception,
      // and convert it to an IOException here.
      throw new IOException(e.getMessage(), e);
    }
  }

  private static final class ManifestLineProcessor implements LineProcessor<FilesetManifest> {
    private final String workspaceName;
    private final PathFragment targetPrefix;
    private final RelativeSymlinkBehavior relSymlinkBehavior;

    private int lineNum;
    private final Map<PathFragment, String> entries = new LinkedHashMap<>();
    private final Map<PathFragment, String> relativeLinks = new HashMap<>();

    ManifestLineProcessor(
        String workspaceName,
        PathFragment targetPrefix,
        RelativeSymlinkBehavior relSymlinkBehavior) {
      this.workspaceName = workspaceName;
      this.targetPrefix = targetPrefix;
      this.relSymlinkBehavior = relSymlinkBehavior;
    }

    @Override
    public boolean processLine(String line) throws IOException {
      if (++lineNum % 2 == 0) {
        // Digest line, skip.
        return true;
      }
      if (line.isEmpty()) {
        return true;
      }

      String artifact;
      PathFragment location;
      int pos = line.indexOf(' ');
      if (pos == -1) {
        location = PathFragment.create(line);
        artifact = null;
      } else {
        location = PathFragment.create(line.substring(0, pos));
        String targetPath = line.substring(pos + 1);
        artifact = targetPath.isEmpty() ? null : targetPath;

        if (!workspaceName.isEmpty()) {
          if (!location.getSegment(0).equals(workspaceName)) {
            throw new IOException(
                String.format(
                    "fileset manifest line must start with '%s': '%s'", workspaceName, location));
          } else {
            // Erase "<workspaceName>/" prefix.
            location = location.subFragment(1);
          }
        }
      }

      PathFragment fullLocation = targetPrefix.getRelative(location);
      if (!entries.containsKey(fullLocation)) {
        boolean isRelativeSymlink = artifact != null && !artifact.startsWith("/");
        if (isRelativeSymlink && relSymlinkBehavior.equals(RelativeSymlinkBehavior.ERROR)) {
          throw new IOException(String.format("runfiles target is not absolute: %s", artifact));
        }
        if (!isRelativeSymlink
            || relSymlinkBehavior.equals(RelativeSymlinkBehavior.RESOLVE)) {
          entries.put(fullLocation, artifact);
          if (artifact != null && !artifact.startsWith("/")) {
            relativeLinks.put(fullLocation, artifact);
          }
        }
      }
      return true;
    }

    @Override
    public FilesetManifest getResult() {
      // Resolve relative symlinks if possible. Note that relativeLinks only contains entries in
      // RESOLVE mode.
      for (Map.Entry<PathFragment, String> e : relativeLinks.entrySet()) {
        PathFragment location = e.getKey();
        String value = e.getValue();
        PathFragment actualLocation = location.getParentDirectory().getRelative(value);
        String actual = entries.get(actualLocation);
        boolean isActualAcceptable = actual == null || actual.startsWith("/");
        if (!entries.containsKey(actualLocation) || !isActualAcceptable) {
          throw new IllegalStateException(
              String.format(
                  "runfiles target '%s' is not absolute, and could not be resolved in the same "
                  + "Fileset", value));
        }
        entries.put(location, actual);
      }
      return new FilesetManifest(entries);
    }
  }

  private final Map<PathFragment, String> entries;

  private FilesetManifest(Map<PathFragment, String> entries) {
    this.entries = Collections.unmodifiableMap(entries);
  }

  public Map<PathFragment, String> getEntries() {
    return entries;
  }
}
