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

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.util.function.Function;
import javax.annotation.Nullable;

/**
 * The representation of a parsed option instance.
 *
 * <p>An option instance is distinct from the final value of an option, as multiple instances
 * provide values may be overridden or combined in some way.
 */
public final class ParsedOptionDescription {

  private final OptionDefinition optionDefinition;
  @Nullable private final String commandLineForm;
  @Nullable private final String unconvertedValue;
  private final OptionInstanceOrigin origin;
  @Nullable private final Object conversionContext;
  private final boolean oldNameUsed;

  private ParsedOptionDescription(
      OptionDefinition optionDefinition,
      @Nullable String commandLineForm,
      @Nullable String unconvertedValue,
      OptionInstanceOrigin origin,
      @Nullable Object conversionContext,
      boolean oldNameUsed) {
    this.optionDefinition = Preconditions.checkNotNull(optionDefinition);
    this.commandLineForm = commandLineForm;
    this.unconvertedValue = unconvertedValue;
    this.origin = Preconditions.checkNotNull(origin);
    this.conversionContext = conversionContext;
    this.oldNameUsed = oldNameUsed;
  }

  static ParsedOptionDescription newParsedOptionDescription(
      OptionDefinition optionDefinition,
      String commandLineForm,
      @Nullable String unconvertedValue,
      OptionInstanceOrigin origin,
      @Nullable Object conversionContext) {
    // An actual ParsedOptionDescription should always have a form in which it was parsed, but some
    // options, such as expansion options, legitimately have no value.
    return new ParsedOptionDescription(
        optionDefinition,
        Preconditions.checkNotNull(commandLineForm),
        unconvertedValue,
        origin,
        conversionContext,
        false);
  }

  static ParsedOptionDescription newParsedOptionDescription(
      OptionDefinition optionDefinition,
      String commandLineForm,
      @Nullable String unconvertedValue,
      OptionInstanceOrigin origin,
      @Nullable Object conversionContext,
      boolean oldNameUsed) {
    // An actual ParsedOptionDescription should always have a form in which it was parsed, but some
    // options, such as expansion options, legitimately have no value.
    return new ParsedOptionDescription(
        optionDefinition,
        Preconditions.checkNotNull(commandLineForm),
        unconvertedValue,
        origin,
        conversionContext,
        oldNameUsed);
  }

  /**
   * This factory should be used when there is no actual parsed option, since in those cases we do
   * not have an original value or form that the option took.
   */
  static ParsedOptionDescription newDummyInstance(
      OptionDefinition optionDefinition,
      OptionInstanceOrigin origin,
      @Nullable Object conversionContext) {
    return new ParsedOptionDescription(
        optionDefinition, null, null, origin, conversionContext, false);
  }

  public OptionDefinition getOptionDefinition() {
    return optionDefinition;
  }

  @Nullable
  public String getCommandLineForm() {
    return commandLineForm;
  }

  public String getCanonicalForm() {
    return getCanonicalFormWithValueEscaper(s -> s);
  }

  public String getCanonicalFormWithValueEscaper(Function<String, String> escapingFunction) {
    // For boolean flags (note that here we do not check for TriState flags, only flags with actual
    // boolean values, so that we know the return type of getConvertedValue), use the --[no]flag
    // form for the canonical value.
    if (optionDefinition.getType().equals(boolean.class)) {
      try {
        return ((boolean) getConvertedValue() ? "--" : "--no") + optionDefinition.getOptionName();
      } catch (OptionsParsingException e) {
        throw new RuntimeException("Unexpected parsing exception", e);
      }
    } else {
      String optionString = "--" + optionDefinition.getOptionName();
      if (unconvertedValue != null) { // Can be null for Void options.
        optionString += "=" + escapingFunction.apply(unconvertedValue);
      }
      return optionString;
    }
  }

  @Deprecated
  // TODO(b/65646296) Once external dependencies are cleaned up, use getCanonicalForm()
  String getDeprecatedCanonicalForm() {
    String value = unconvertedValue;
    // For boolean flags (note that here we do not check for TriState flags, only flags with actual
    // boolean values, so that we know the return type of getConvertedValue), set them all to 1 or
    // 0, instead of keeping the wide variety of values we accept in their original form.
    if (optionDefinition.getType().equals(boolean.class)) {
      try {
        value = (boolean) getConvertedValue() ? "1" : "0";
      } catch (OptionsParsingException e) {
        throw new RuntimeException("Unexpected parsing exception", e);
      }
    }
    return String.format("--%s=%s", optionDefinition.getOptionName(), value);
  }

  public boolean isBooleanOption() {
    return optionDefinition.getType().equals(boolean.class);
  }

  private OptionDocumentationCategory documentationCategory() {
    return optionDefinition.getDocumentationCategory();
  }

  private ImmutableList<OptionMetadataTag> metadataTags() {
    return ImmutableList.copyOf(optionDefinition.getOptionMetadataTags());
  }

  public boolean isDocumented() {
    return documentationCategory() != OptionDocumentationCategory.UNDOCUMENTED && !isHidden();
  }

  public boolean isHidden() {
    ImmutableList<OptionMetadataTag> tags = metadataTags();
    return tags.contains(OptionMetadataTag.HIDDEN) || tags.contains(OptionMetadataTag.INTERNAL);
  }

  @Nullable
  public String getUnconvertedValue() {
    return unconvertedValue;
  }

  public OptionInstanceOrigin getOrigin() {
    return origin;
  }

  public OptionPriority getPriority() {
    return origin.getPriority();
  }

  public boolean isOldNameUsed() {
    return oldNameUsed;
  }

  @Nullable
  public String getSource() {
    return origin.getSource();
  }

  @Nullable
  ParsedOptionDescription getImplicitDependent() {
    return origin.getImplicitDependent();
  }

  @Nullable
  ParsedOptionDescription getExpandedFrom() {
    return origin.getExpandedFrom();
  }

  public boolean isExplicit() {
    return origin.getExpandedFrom() == null && origin.getImplicitDependent() == null;
  }

  public Object getConvertedValue() throws OptionsParsingException {
    Converter<?> converter = optionDefinition.getConverter();
    try {
      return converter.convert(unconvertedValue, conversionContext);
    } catch (OptionsParsingException e) {
      // The converter doesn't know the option name, so we supply it here by re-throwing:
      throw new OptionsParsingException(
          String.format("While parsing option %s: %s", commandLineForm, e.getMessage()), e);
    }
  }

  @Override
  public String toString() {
    // Check that a dummy value-less option instance does not output all the default information.
    if (commandLineForm == null) {
      return optionDefinition.toString();
    }
    String source = origin.getSource();
    return String.format(
        "option '%s'%s",
        commandLineForm, source == null ? "" : String.format(" (source %s)", source));
  }
}
