// Copyright 2019 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.skyframe;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.FileValue;
import com.google.devtools.build.lib.actions.MissingInputFileException;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyFunctionException;
import com.google.devtools.build.skyframe.SkyKey;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nullable;

/**
 * Function that reads the contents of a mapping file specified in {@code --platform_mappings} and
 * parses them for use in a {@link PlatformMappingValue}.
 *
 * <p>Note that this class only parses the mapping-file specific format, parsing (and validation) of
 * flags contained therein is left to the invocation of {@link
 * PlatformMappingValue#map(BuildConfigurationValue.Key, BuildOptions)}.
 */
public class PlatformMappingFunction implements SkyFunction {

  @Nullable
  @Override
  public PlatformMappingValue compute(SkyKey skyKey, Environment env)
      throws PlatformMappingException, InterruptedException {
    PlatformMappingValue.Key platformMappingKey = (PlatformMappingValue.Key) skyKey.argument();
    PathFragment workspaceRelativeMappingPath =
        platformMappingKey.getWorkspaceRelativeMappingPath();

    PathPackageLocator pkgLocator = PrecomputedValue.PATH_PACKAGE_LOCATOR.get(env);
    if (pkgLocator == null) {
      return null;
    }

    ImmutableList<Root> pathEntries = pkgLocator.getPathEntries();
    for (Root root : pathEntries) {
      RootedPath rootedMappingPath = RootedPath.toRootedPath(root, workspaceRelativeMappingPath);
      FileValue fileValue = (FileValue) env.getValue(FileValue.key(rootedMappingPath));
      if (fileValue == null) {
        return null;
      }

      if (!fileValue.exists()) {
        continue;
      }
      if (fileValue.isDirectory()) {
        throw new PlatformMappingException(
            new MissingInputFileException(
                String.format(
                    "--platform_mappings was set to '%s' relative to the top-level workspace '%s'"
                        + " but that path refers to a directory, not a file",
                    workspaceRelativeMappingPath, root),
                Location.BUILTIN),
            SkyFunctionException.Transience.PERSISTENT);
      }

      Iterable<String> lines;
      try {
        lines =
            FileSystemUtils.readLines(fileValue.realRootedPath().asPath(), StandardCharsets.UTF_8);
      } catch (IOException e) {
        throw new PlatformMappingException(e, SkyFunctionException.Transience.TRANSIENT);
      }

      return new Parser(lines.iterator()).parse().toPlatformMappingValue();
    }

    if (!platformMappingKey.wasExplicitlySetByUser()) {
      // If no flag was passed and the default mapping file does not exist treat this as if the
      // mapping file was empty rather than an error.
      return PlatformMappingValue.EMPTY;
    }
    throw new PlatformMappingException(
        new MissingInputFileException(
            String.format(
                "--platform_mappings was set to '%s' but no such file exists relative to the "
                    + "package path roots, '%s'",
                workspaceRelativeMappingPath, pathEntries),
            Location.BUILTIN),
        SkyFunctionException.Transience.PERSISTENT);
  }

  @Nullable
  @Override
  public String extractTag(SkyKey skyKey) {
    return null;
  }

  @VisibleForTesting
  static class PlatformMappingException extends SkyFunctionException {

    public PlatformMappingException(Exception cause, Transience transience) {
      super(cause, transience);
    }
  }

  @VisibleForTesting
  static class Parser {

    private final Iterator<String> lines;

    /**
     * Using an optional to represent the next line with contents, {@link Optional#empty()} if we
     * reached end of file.
     *
     * <p>Stores the current non-comment, non-empty, non-whitespace line. Don't access the field
     * directly, it can either be "used up" by calling {@link #consume()} or retrieved without
     * moving on by calling {@link #peek()}.
     */
    private Optional<String> line;

    Parser(Iterator<String> lines) {
      this.lines = lines;
    }

    Mappings parse() throws PlatformMappingException {
      goToNextContentLine();

      if (!line.isPresent()) {
        return new Mappings(ImmutableMap.of(), ImmutableMap.of());
      }

      Map<Label, Collection<String>> platformsToFlags = ImmutableMap.of();
      Map<Collection<String>, Label> flagsToPlatforms = ImmutableMap.of();

      if (!peek().equalsIgnoreCase("platforms:") && !peek().equalsIgnoreCase("flags:")) {
        throwParsingException("Expected 'platforms:' or 'flags:' but got " + peek());
      }

      if (peek().equalsIgnoreCase("platforms:")) {
        consume();
        platformsToFlags = platformsToFlags();
      }

      if (line.isPresent()) {
        if (!peek().equalsIgnoreCase("flags:")) {
          throwParsingException("Expected 'flags:' but got " + peek());
        }
        consume();
        flagsToPlatforms = flagsToPlatforms();
      }

      if (line.isPresent()) {
        throwParsingException("Expected end of file but got " + peek());
      }
      return new Mappings(platformsToFlags, flagsToPlatforms);
    }

    private Map<Label, Collection<String>> platformsToFlags() throws PlatformMappingException {
      ImmutableMap.Builder<Label, Collection<String>> platformsToFlags = ImmutableMap.builder();
      while (line.isPresent() && !peek().equalsIgnoreCase("flags:")) {
        Label platform = platform();
        Collection<String> flags = flags();
        platformsToFlags.put(platform, flags);
      }

      try {
        return platformsToFlags.build();
      } catch (IllegalArgumentException e) {
        throw throwParsingException(
            e, "Got duplicate platform entries but each platform key must be unique");
      }
    }

    private Label platform() throws PlatformMappingException {
      if (!line.isPresent()) {
        throwParsingException("Expected platform label but got end of file");
      }
      String label = consume();

      Label platform;
      try {
        ImmutableMap<RepositoryName, RepositoryName> emptyRepositoryMapping = ImmutableMap.of();
        // It is ok for us to use an empty repository mapping in this instance because all platform
        // labels used in the mapping file should be relative to the root repository. Repository
        // mappings however only apply within a repository imported by the root repository.
        platform = Label.parseAbsolute(label, emptyRepositoryMapping);
      } catch (LabelSyntaxException e) {
        throw throwParsingException(e, "Expected platform label but got " + label);
      }
      return platform;
    }

    private Collection<String> flags() throws PlatformMappingException {
      ImmutableSet.Builder<String> flags = ImmutableSet.builder();
      // Note: Short form flags are not supported.
      while (lineIsFlag()) {
        flags.add(consume());
      }
      ImmutableSet<String> parsedFlags = flags.build();
      if (parsedFlags.isEmpty()) {
        if (!line.isPresent()) {
          throwParsingException("Expected a flag but got end of file");
        }
        throwParsingException(
            "Expected a standard format flag (starting with --) but got " + peek());
      }

      return parsedFlags;
    }

    private Map<Collection<String>, Label> flagsToPlatforms() throws PlatformMappingException {
      ImmutableMap.Builder<Collection<String>, Label> flagsToPlatforms = ImmutableMap.builder();
      while (lineIsFlag()) {
        Collection<String> flags = flags();
        Label platform = platform();
        flagsToPlatforms.put(flags, platform);
      }
      try {
        return flagsToPlatforms.build();
      } catch (IllegalArgumentException e) {
        throw throwParsingException(
            e, "Got duplicate flags entries but each flags key must be unique");
      }
    }

    private String consume() {
      Preconditions.checkState(
          line.isPresent(), "Must make sure that a line exists before consuming.");
      String value = line.get();
      goToNextContentLine();
      return value;
    }

    private String peek() {
      Preconditions.checkState(
          line.isPresent(), "Must make sure that a line exists before peeking.");
      return line.get();
    }

    private AssertionError throwParsingException(Exception e, String message)
        throws PlatformMappingException {
      throw new PlatformMappingException(
          new PlatformMappingParsingException(message, e),
          SkyFunctionException.Transience.PERSISTENT);
    }

    private void throwParsingException(String message) throws PlatformMappingException {
      throw new PlatformMappingException(
          new PlatformMappingParsingException(message), SkyFunctionException.Transience.PERSISTENT);
    }

    private boolean lineIsFlag() {
      return line.isPresent() && peek().startsWith("--");
    }

    private void goToNextContentLine() {
      while (lines.hasNext()) {
        String line = lines.next().trim();
        if (line.isEmpty() || line.startsWith("#")) {
          continue;
        }
        this.line = Optional.of(line);
        return;
      }
      line = Optional.empty();
    }
  }

  /**
   * Simple data holder to make testing easier. Only for use internal to this file/tests thereof.
   */
  @VisibleForTesting
  static class Mappings {
    final Map<Label, Collection<String>> platformsToFlags;
    final Map<Collection<String>, Label> flagsToPlatforms;

    Mappings(
        Map<Label, Collection<String>> platformsToFlags,
        Map<Collection<String>, Label> flagsToPlatforms) {
      this.platformsToFlags = platformsToFlags;
      this.flagsToPlatforms = flagsToPlatforms;
    }

    PlatformMappingValue toPlatformMappingValue() {
      return new PlatformMappingValue(platformsToFlags, flagsToPlatforms);
    }
  }

  /**
   * Inner wrapper exception to work around the fact that {@link SkyFunctionException} cannot carry
   * a message of its own.
   */
  private static class PlatformMappingParsingException extends Exception {
    public PlatformMappingParsingException(String message) {
      super(message);
    }

    public PlatformMappingParsingException(String message, Throwable cause) {
      super(message, cause);
    }
  }
}
