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

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.events.EventKind;
import com.google.devtools.common.options.Converter;
import com.google.devtools.common.options.Converters.CommaSeparatedOptionListConverter;
import com.google.devtools.common.options.Converters.RangeConverter;
import com.google.devtools.common.options.EnumConverter;
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.OptionMetadataTag;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParsingException;
import java.util.HashSet;
import java.util.List;

/** Command-line UI options. */
public class UiOptions extends OptionsBase {

  /** Enum to select whether color output is enabled or not. */
  public enum UseColor {
    YES,
    NO,
    AUTO
  }

  /** Enum to select whether curses output is enabled or not. */
  public enum UseCurses {
    YES,
    NO,
    AUTO
  }

  /** Converter for {@link EventKind} filters * */
  public static class EventFiltersConverter
      extends Converter.Contextless<EventFiltersConverter.EventKindFilters> {

    /** Container for an EventKind input filter. */
    @AutoValue
    public abstract static class EventKindFilters {
      public abstract ImmutableSet<EventKind> getFilteredEventKinds();

      public abstract ImmutableSet<EventKind> getUnfilteredEventKinds();

      public static EventKindFilters from(
          ImmutableSet<EventKind> filtered, ImmutableSet<EventKind> unfiltered) {
        return new AutoValue_UiOptions_EventFiltersConverter_EventKindFilters(filtered, unfiltered);
      }
    }

    private final CommaSeparatedOptionListConverter commaSeparatedListConverter;
    private final EnumConverter<EventKind> eventKindConverter;

    public EventFiltersConverter() {
      this.commaSeparatedListConverter = new CommaSeparatedOptionListConverter();
      this.eventKindConverter = new EnumConverter<>(EventKind.class, "event kind") {};
    }

    @Override
    public EventKindFilters convert(String input) throws OptionsParsingException {
      if (input.isEmpty()) {
        // This method is not called to convert the default value
        // Empty list means that the user wants to filter all events
        return EventKindFilters.from(EventKind.ALL_EVENTS, ImmutableSet.of());
      }
      ImmutableList<String> filters =
          commaSeparatedListConverter.convert(input, /* conversionContext= */ null);

      HashSet<EventKind> filteredEventKinds = new HashSet<>();
      HashSet<EventKind> unfilteredEventKinds = new HashSet<>();

      for (String filter : filters) {
        if (!filter.startsWith("+") && !filter.startsWith("-")) {
          filteredEventKinds.addAll(EventKind.ALL_EVENTS);
          unfilteredEventKinds.clear();
        }
        if (!filter.isEmpty()) {
          EventKind kind =
              eventKindConverter.convert(
                  filter.replaceFirst("^[+-]", ""), /* conversionContext= */ null);
          if (filter.startsWith("-")) {
            filteredEventKinds.add(kind);
            unfilteredEventKinds.remove(kind);
          } else {
            unfilteredEventKinds.add(kind);
            filteredEventKinds.remove(kind);
          }
        }
      }
      return EventKindFilters.from(
          ImmutableSet.copyOf(filteredEventKinds), ImmutableSet.copyOf(unfilteredEventKinds));
    }

    @Override
    public String getTypeDescription() {
      return "Convert list of comma separated event kind to list of filters";
    }
  }

  /** Converter for {@link UseColor}. */
  public static class UseColorConverter extends EnumConverter<UseColor> {
    public UseColorConverter() {
      super(UseColor.class, "--color setting");
    }
  }

  /** Converter for {@link UseCurses}. */
  public static class UseCursesConverter extends EnumConverter<UseCurses> {
    public UseCursesConverter() {
      super(UseCurses.class, "--curses setting");
    }
  }

  @Option(
      name = "show_progress",
      defaultValue = "true",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "Display progress messages during a build.")
  public boolean showProgress;

  @Option(
      name = "show_progress_rate_limit",
      defaultValue = "0.2", // A nice middle ground; snappy but not too spammy in logs.
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "Minimum number of seconds between progress messages in the output.")
  public double showProgressRateLimit;

  @Option(
      name = "color",
      defaultValue = "auto",
      converter = UseColorConverter.class,
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "Use terminal controls to colorize output.")
  public UseColor useColorEnum;

  @Option(
      name = "curses",
      defaultValue = "auto",
      converter = UseCursesConverter.class,
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "Use terminal cursor controls to minimize scrolling output.")
  public UseCurses useCursesEnum;

  @Option(
      name = "terminal_columns",
      defaultValue = "80",
      metadataTags = {OptionMetadataTag.HIDDEN},
      documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "A system-generated parameter which specifies the terminal width in columns.")
  public int terminalColumns;

  @Option(
      name = "isatty",
      defaultValue = "false",
      metadataTags = {OptionMetadataTag.HIDDEN},
      documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help =
          "A system-generated parameter which is used to notify the "
              + "server whether this client is running in a terminal. "
              + "If this is set to false, then '--color=auto' will be treated as '--color=no'. "
              + "If this is set to true, then '--color=auto' will be treated as '--color=yes'.")
  public boolean isATty;

  // This lives here (as opposed to the more logical BuildRequest.Options)
  // because the client passes it to the server *always*.  We don't want the
  // client to have to figure out when it should or shouldn't to send it.
  @Option(
      name = "emacs",
      defaultValue = "false",
      documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help =
          "A system-generated parameter which is true iff EMACS=t or INSIDE_EMACS is set "
              + "in the environment of the client.  This option controls certain display "
              + "features.")
  public boolean runningInEmacs;

  @Option(
      name = "show_timestamps",
      defaultValue = "false",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "Include timestamps in messages")
  public boolean showTimestamp;

  @Option(
      name = "progress_in_terminal_title",
      defaultValue = "false",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help =
          "Show the command progress in the terminal title. "
              + "Useful to see what bazel is doing when having multiple terminal tabs.")
  public boolean progressInTermTitle;

  @Option(
      name = "attempt_to_print_relative_paths",
      oldName = "experimental_ui_attempt_to_print_relative_paths",
      defaultValue = "false",
      documentationCategory = OptionDocumentationCategory.LOGGING,
      effectTags = {OptionEffectTag.TERMINAL_OUTPUT},
      help =
          "When printing the location part of messages, attempt to use a path relative to the "
              + "workspace directory or one of the directories specified by --package_path.")
  public boolean attemptToPrintRelativePaths;

  @Option(
      name = "experimental_ui_debug_all_events",
      defaultValue = "false",
      metadataTags = {OptionMetadataTag.HIDDEN},
      documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "Report all events known to the Bazel UI.")
  public boolean experimentalUiDebugAllEvents;

  @Option(
      name = "ui_event_filters",
      converter = EventFiltersConverter.class,
      defaultValue = "null",
      documentationCategory = OptionDocumentationCategory.LOGGING,
      effectTags = {OptionEffectTag.TERMINAL_OUTPUT},
      help =
          "Specifies which events to show in the UI. It is possible to add or remove events "
              + "to the default ones using leading +/-, or override the default "
              + "set completely with direct assignment. The set of supported event kinds "
              + "include INFO, DEBUG, ERROR and more.",
      allowMultiple = true)
  public List<EventFiltersConverter.EventKindFilters> eventKindFilters;

  @Option(
      name = "ui_actions_shown",
      oldName = "experimental_ui_actions_shown",
      defaultValue = "8",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.TERMINAL_OUTPUT},
      help =
          "Number of concurrent actions shown in the detailed progress bar; each "
              + "action is shown on a separate line. The progress bar always shows "
              + "at least one one, all numbers less than 1 are mapped to 1.")
  public int uiActionsShown;

  @Option(
      name = "experimental_ui_max_stdouterr_bytes",
      documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY,
      effectTags = {OptionEffectTag.EXECUTION},
      defaultValue = "1048576",
      converter = MaxStdoutErrBytesConverter.class,
      help =
          "The maximum size of the stdout / stderr files that will be printed to the console. "
              + "-1 implies no limit.")
  public int maxStdoutErrBytes;

  public boolean useColor() {
    return useColorEnum == UseColor.YES || (useColorEnum == UseColor.AUTO && isATty);
  }

  public boolean useCursorControl() {
    return useCursesEnum == UseCurses.YES || (useCursesEnum == UseCurses.AUTO && isATty);
  }

  public ImmutableSet<EventKind> getFilteredEventKinds() {
    HashSet<EventKind> filtered = new HashSet<>();
    for (EventFiltersConverter.EventKindFilters filters : eventKindFilters) {
      filtered.addAll(filters.getFilteredEventKinds());
      filtered.removeAll(filters.getUnfilteredEventKinds());
    }
    return ImmutableSet.copyOf(filtered);
  }

  /** A converter for --experimental_ui_max_stdouterr_bytes. */
  public static class MaxStdoutErrBytesConverter extends RangeConverter {

    /**
     * The maximum value of the flag must be limited to ensure conversions to UTF-8 do not trigger
     * integer overflows. In JDK9+, if the message buffer contains a byte whose high bit is set, a
     * UTF-8 decoding path is taken that allocates a new byte[] buffer twice as large as the message
     * byte[] buffer.
     */
    private static final int MAX_VALUE = (Integer.MAX_VALUE - 8) >> 1;

    public MaxStdoutErrBytesConverter() {
      super(-1, (Integer.MAX_VALUE - 8) >> 1);
    }

    @Override
    public Integer convert(String input) throws OptionsParsingException {
      Integer value = super.convert(input);
      return value >= 0 ? value : MAX_VALUE;
    }
  }
}
