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

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.base.StandardSystemProperty;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.common.options.Converter;
import com.google.devtools.common.options.OptionsParsingException;
import com.google.devtools.common.options.OptionsParsingResult;
import com.google.devtools.common.options.ParsedOptionDescription;
import java.util.List;
import javax.annotation.Nullable;

/** Blaze-specific option utilities. */
public final class OptionsUtils {

  /**
   * Returns a string representation of the non-hidden specified options; option values are
   * shell-escaped.
   */
  public static String asShellEscapedString(Iterable<ParsedOptionDescription> optionsList) {
    StringBuilder result = new StringBuilder();
    for (ParsedOptionDescription option : optionsList) {
      if (option.isHidden()) {
        continue;
      }
      if (result.length() != 0) {
        result.append(' ');
      }
      result.append(option.getCanonicalFormWithValueEscaper(ShellEscaper::escapeString));
    }
    return result.toString();
  }

  /**
   * Returns a string representation of the non-hidden explicitly or implicitly specified options;
   * option values are shell-escaped.
   */
  public static String asShellEscapedString(OptionsParsingResult options) {
    return asShellEscapedString(options.asCompleteListOfParsedOptions());
  }

  /**
   * Return a representation of the non-hidden specified options, as a list of string. No escaping
   * is done.
   */
  public static List<String> asArgumentList(Iterable<ParsedOptionDescription> optionsList) {
    ImmutableList.Builder<String> builder = ImmutableList.builder();
    for (ParsedOptionDescription option : optionsList) {
      if (option.isHidden()) {
        continue;
      }
      builder.add(option.getCanonicalForm());
    }
    return builder.build();
  }

  /**
   * Return a representation of the non-hidden specified options, as a list of string. No escaping
   * is done.
   */
  public static List<String> asArgumentList(OptionsParsingResult options) {
    return asArgumentList(options.asCompleteListOfParsedOptions());
  }

  /**
   * Returns a string representation of the non-hidden explicitly or implicitly specified options,
   * filtering out any sensitive options; option values are shell-escaped.
   */
  public static String asFilteredShellEscapedString(
      OptionsParsingResult options, Iterable<ParsedOptionDescription> optionsList) {
    return asShellEscapedString(optionsList);
  }

  /**
   * Returns a string representation of the non-hidden explicitly or implicitly specified options,
   * filtering out any sensitive options; option values are shell-escaped.
   */
  public static String asFilteredShellEscapedString(OptionsParsingResult options) {
    return asFilteredShellEscapedString(options, options.asCompleteListOfParsedOptions());
  }

  /** Converter from String to PathFragment. */
  public static class PathFragmentConverter extends Converter.Contextless<PathFragment> {

    @Override
    public PathFragment convert(String input) {
      return convertOptionsPathFragment(checkNotNull(input));
    }

    @Override
    public String getTypeDescription() {
      return "a path";
    }
  }

  /** Converter from String to PathFragment. If the input is empty returns {@code null} instead. */
  public static class EmptyToNullPathFragmentConverter extends Converter.Contextless<PathFragment> {

    @Override
    @Nullable
    public PathFragment convert(String input) throws OptionsParsingException {
      if (input.isEmpty()) {
        return null;
      }
      return convertOptionsPathFragment(input);
    }

    @Override
    public String getTypeDescription() {
      return "a path";
    }
  }

  /** Converter from String to PathFragment requiring the provided path to be absolute. */
  public static class AbsolutePathFragmentConverter extends Converter.Contextless<PathFragment> {

    @Override
    public PathFragment convert(String input) throws OptionsParsingException {
      PathFragment parsed = convertOptionsPathFragment(checkNotNull(input));
      if (!parsed.isAbsolute()) {
        throw new OptionsParsingException(String.format("Not an absolute path: '%s'", input));
      }
      return parsed;
    }

    @Override
    public String getTypeDescription() {
      return "an absolute path";
    }
  }

  /**
   * Converter from String to PathFragment requiring the provided path to be relative. If the input
   * is empty returns {@code null} instead.
   */
  public static class EmptyToNullRelativePathFragmentConverter
      extends Converter.Contextless<PathFragment> {

    @Override
    @Nullable
    public PathFragment convert(String input) throws OptionsParsingException {
      if (input.isEmpty()) {
        return null;
      }

      PathFragment pathFragment = convertOptionsPathFragment(input);

      if (pathFragment.isAbsolute()) {
        throw new OptionsParsingException("Expected relative path but got '" + input + "'.");
      }

      return pathFragment;
    }

    @Override
    public String getTypeDescription() {
      return "a relative path";
    }
  }

  /** Converts from a colon-separated list of strings into a list of PathFragment instances. */
  public static class PathFragmentListConverter
      extends Converter.Contextless<ImmutableList<PathFragment>> {

    @Override
    public ImmutableList<PathFragment> convert(String input) {
      ImmutableList.Builder<PathFragment> result = ImmutableList.builder();
      for (String piece : input.split(":")) {
        if (!piece.isEmpty()) {
          result.add(convertOptionsPathFragment(piece));
        }
      }
      return result.build();
    }

    @Override
    public String getTypeDescription() {
      return "a colon-separated list of paths";
    }
  }

  private static PathFragment convertOptionsPathFragment(String path) {
    if (!path.isEmpty() && path.startsWith("~/")) {
      path = path.replace("~", StandardSystemProperty.USER_HOME.value());
    }
    return PathFragment.create(path);
  }
}
