// 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.common.options;

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.escape.Escaper;
import java.lang.reflect.Field;
import java.text.BreakIterator;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.annotation.Nullable;

/**
 * A renderer for usage messages. For now this is very simple.
 */
class OptionsUsage {

  private static final Splitter NEWLINE_SPLITTER = Splitter.on('\n');
  private static final Joiner COMMA_JOINER = Joiner.on(",");

  /**
   * Given an options class, render the usage string into the usage, which is passed in as an
   * argument. This will not include information about expansions for options using expansion
   * functions (it would be unsafe to report this as we cannot know what options from other {@link
   * OptionsBase} subclasses they depend on until a complete parser is constructed).
   */
  static void getUsage(Class<? extends OptionsBase> optionsClass, StringBuilder usage) {
    List<Field> optionFields =
        Lists.newArrayList(OptionsParser.getAllAnnotatedFields(optionsClass));
    Collections.sort(optionFields, BY_NAME);
    for (Field optionField : optionFields) {
      getUsage(optionField, usage, OptionsParser.HelpVerbosity.LONG, null);
    }
  }

  /**
   * Paragraph-fill the specified input text, indenting lines to 'indent' and
   * wrapping lines at 'width'.  Returns the formatted result.
   */
  static String paragraphFill(String in, int indent, int width) {
    String indentString = Strings.repeat(" ", indent);
    StringBuilder out = new StringBuilder();
    String sep = "";
    for (String paragraph : NEWLINE_SPLITTER.split(in)) {
      BreakIterator boundary = BreakIterator.getLineInstance(); // (factory)
      boundary.setText(paragraph);
      out.append(sep).append(indentString);
      int cursor = indent;
      for (int start = boundary.first(), end = boundary.next();
           end != BreakIterator.DONE;
           start = end, end = boundary.next()) {
        String word =
            paragraph.substring(start, end); // (may include trailing space)
        if (word.length() + cursor > width) {
          out.append('\n').append(indentString);
          cursor = indent;
        }
        out.append(word);
        cursor += word.length();
      }
      sep = "\n";
    }
    return out.toString();
  }

  /**
   * Returns the expansion for an option, to the extent known. Precisely, if an {@link OptionsData}
   * object is supplied, the expansion is read from that. Otherwise, the annotation is inspected: If
   * the annotation uses {@link Option#expansion} it is returned, and if it uses {@link
   * Option#expansionFunction} null is returned, indicating a lack of definite information. In all
   * cases, when the option is not an expansion option, an empty array is returned.
   */
  private static @Nullable String[] getExpansionIfKnown(
      Field optionField, Option annotation, @Nullable OptionsData optionsData) {
    if (optionsData != null) {
      return optionsData.getEvaluatedExpansion(optionField);
    } else {
      if (OptionsData.usesExpansionFunction(annotation)) {
        return null;
      } else {
        // Empty array if it's not an expansion option.
        return annotation.expansion();
      }
    }
  }

  /**
   * Appends the usage message for a single option-field message to 'usage'. If {@code optionsData}
   * is not supplied, options that use expansion functions won't be fully described.
   */
  static void getUsage(
      Field optionField,
      StringBuilder usage,
      OptionsParser.HelpVerbosity helpVerbosity,
      @Nullable OptionsData optionsData) {
    String flagName = getFlagName(optionField);
    String typeDescription = getTypeDescription(optionField);
    Option annotation = optionField.getAnnotation(Option.class);
    usage.append("  --" + flagName);
    if (helpVerbosity == OptionsParser.HelpVerbosity.SHORT) { // just the name
      usage.append('\n');
      return;
    }
    if (annotation.abbrev() != '\0') {
      usage.append(" [-").append(annotation.abbrev()).append(']');
    }
    if (!typeDescription.equals("")) {
      usage.append(" (" + typeDescription + "; ");
      if (annotation.allowMultiple()) {
        usage.append("may be used multiple times");
      } else {
        // Don't call the annotation directly (we must allow overrides to certain defaults)
        String defaultValueString = OptionsParserImpl.getDefaultOptionString(optionField);
        if (OptionsParserImpl.isSpecialNullDefault(defaultValueString, optionField)) {
          usage.append("default: see description");
        } else {
          usage.append("default: \"" + defaultValueString + "\"");
        }
      }
      usage.append(")");
    }
    usage.append("\n");
    if (helpVerbosity == OptionsParser.HelpVerbosity.MEDIUM) { // just the name and type.
      return;
    }
    if (!annotation.help().equals("")) {
      usage.append(paragraphFill(annotation.help(), 4, 80)); // (indent, width)
      usage.append('\n');
    }
    String[] expansion = getExpansionIfKnown(optionField, annotation, optionsData);
    if (expansion == null) {
      usage.append("    Expands to unknown options.\n");
    } else if (expansion.length > 0) {
      StringBuilder expandsMsg = new StringBuilder("Expands to: ");
      for (String exp : expansion) {
        expandsMsg.append(exp).append(" ");
      }
      usage.append(paragraphFill(expandsMsg.toString(), 4, 80)); // (indent, width)
      usage.append('\n');
    }
  }

  /**
   * Append the usage message for a single option-field message to 'usage'. If {@code optionsData}
   * is not supplied, options that use expansion functions won't be fully described.
   */
  static void getUsageHtml(
      Field optionField, StringBuilder usage, Escaper escaper, @Nullable OptionsData optionsData) {
    String plainFlagName = optionField.getAnnotation(Option.class).name();
    String flagName = getFlagName(optionField);
    String valueDescription = optionField.getAnnotation(Option.class).valueHelp();
    String typeDescription = getTypeDescription(optionField);
    Option annotation = optionField.getAnnotation(Option.class);
    usage.append("<dt><code><a name=\"flag--").append(plainFlagName).append("\"></a>--");
    usage.append(flagName);
    if (OptionsData.isBooleanField(optionField) || OptionsData.isVoidField(optionField)) {
      // Nothing for boolean, tristate, boolean_or_enum, or void options.
    } else if (!valueDescription.isEmpty()) {
      usage.append("=").append(escaper.escape(valueDescription));
    } else if (!typeDescription.isEmpty()) {
      // Generic fallback, which isn't very good.
      usage.append("=&lt;").append(escaper.escape(typeDescription)).append("&gt");
    }
    usage.append("</code>");
    if (annotation.abbrev() != '\0') {
      usage.append(" [<code>-").append(annotation.abbrev()).append("</code>]");
    }
    if (annotation.allowMultiple()) {
      // Allow-multiple options can't have a default value.
      usage.append(" multiple uses are accumulated");
    } else {
      // Don't call the annotation directly (we must allow overrides to certain defaults).
      String defaultValueString = OptionsParserImpl.getDefaultOptionString(optionField);
      if (OptionsData.isVoidField(optionField)) {
        // Void options don't have a default.
      } else if (OptionsParserImpl.isSpecialNullDefault(defaultValueString, optionField)) {
        usage.append(" default: see description");
      } else {
        usage.append(" default: \"").append(escaper.escape(defaultValueString)).append("\"");
      }
    }
    usage.append("</dt>\n");
    usage.append("<dd>\n");
    if (!annotation.help().isEmpty()) {
      usage.append(paragraphFill(escaper.escape(annotation.help()), 0, 80)); // (indent, width)
      usage.append('\n');
    }
    String[] expansion = getExpansionIfKnown(optionField, annotation, optionsData);
    if (expansion == null) {
      usage.append("    Expands to unknown options.<br>\n");
    } else if (expansion.length > 0) {
      usage.append("<br/>\n");
      StringBuilder expandsMsg = new StringBuilder("Expands to:<br/>\n");
      for (String exp : expansion) {
        // TODO(ulfjack): Can we link to the expanded flags here?
        expandsMsg
            .append("&nbsp;&nbsp;<code>")
            .append(escaper.escape(exp))
            .append("</code><br/>\n");
      }
      usage.append(expandsMsg.toString()); // (indent, width)
      usage.append('\n');
    }
    usage.append("</dd>\n");
  }

  /**
   * Returns the available completion for the given option field. The completions are the exact
   * command line option (with the prepending '--') that one should pass. It is suitable for
   * completion script to use. If the option expect an argument, the kind of argument is given
   * after the equals. If the kind is a enum, the various enum values are given inside an accolade
   * in a comma separated list. For other special kind, the type is given as a name (e.g.,
   * <code>label</code>, <code>float</ode>, <code>path</code>...). Example outputs of this
   * function are for, respectively, a tristate flag <code>tristate_flag</code>, a enum
   * flag <code>enum_flag</code> which can take <code>value1</code>, <code>value2</code> and
   * <code>value3</code>, a path fragment flag <code>path_flag</code>, a string flag
   * <code>string_flag</code> and a void flag <code>void_flag</code>:
   * <pre>
   *   --tristate_flag={auto,yes,no}
   *   --notristate_flag
   *   --enum_flag={value1,value2,value3}
   *   --path_flag=path
   *   --string_flag=
   *   --void_flag
   * </pre>
   *
   * @param field The field to return completion for
   * @param builder the string builder to store the completion values
   */
  static void getCompletion(Field field, StringBuilder builder) {
    // Return the list of possible completions for this option
    String flagName = field.getAnnotation(Option.class).name();
    Class<?> fieldType = field.getType();
    builder.append("--").append(flagName);
    if (fieldType.equals(boolean.class)) {
      builder.append("\n");
      builder.append("--no").append(flagName).append("\n");
    } else if (fieldType.equals(TriState.class)) {
      builder.append("={auto,yes,no}\n");
      builder.append("--no").append(flagName).append("\n");
    } else if (fieldType.isEnum()) {
      builder.append("={")
          .append(COMMA_JOINER.join(fieldType.getEnumConstants()).toLowerCase()).append("}\n");
    } else if (fieldType.getSimpleName().equals("Label")) {
      // String comparison so we don't introduce a dependency to com.google.devtools.build.lib.
      builder.append("=label\n");
    } else if (fieldType.getSimpleName().equals("PathFragment")) {
      builder.append("=path\n");
    } else if (Void.class.isAssignableFrom(fieldType)) {
      builder.append("\n");
    } else {
      // TODO(bazel-team): add more types. Maybe even move the completion type
      // to the @Option annotation?
      builder.append("=\n");
    }
  }

  private static final Comparator<Field> BY_NAME = new Comparator<Field>() {
    @Override
    public int compare(Field left, Field right) {
      return left.getName().compareTo(right.getName());
    }
  };

  /**
   * An ordering relation for option-field fields that first groups together
   * options of the same category, then sorts by name within the category.
   */
  static final Comparator<Field> BY_CATEGORY = new Comparator<Field>() {
    @Override
    public int compare(Field left, Field right) {
      int r = left.getAnnotation(Option.class).category().compareTo(
              right.getAnnotation(Option.class).category());
      return r == 0 ? BY_NAME.compare(left, right) : r;
    }
  };

  private static String getTypeDescription(Field optionsField) {
    return OptionsData.findConverter(optionsField).getTypeDescription();
  }

  static String getFlagName(Field field) {
    String name = field.getAnnotation(Option.class).name();
    return OptionsData.isBooleanField(field) ? "[no]" + name : name;
  }

}
