// Copyright 2015 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.rules.apple;

import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skylarkbuildapi.apple.DottedVersionApi;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
import java.util.ArrayList;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;

/**
 * Represents a value with multiple components, separated by periods, for example {@code 4.5.6} or
 * {@code 5.0.1beta2}. Components must start with a non-negative integer and at least one component
 * must be present.
 *
 * <p>Specifically, the format of a component is {@code \d+([a-z0-9]*?)?(\d+)?}.
 *
 * <p>Dotted versions are ordered using natural integer sorting on components in order from first to
 * last where any missing element is considered to have the value 0 if they don't contain any
 * non-numeric characters. For example:
 *
 * <pre>
 *   3.1.25 > 3.1.1
 *   3.1.20 > 3.1.2
 *   3.1.1 > 3.1
 *   3.1 == 3.1.0.0
 *   3.2 > 3.1.8
 * </pre>
 *
 * <p>If the component contains any alphabetic characters after the leading integer, it is
 * considered <strong>smaller</strong> than any components with the same integer but larger than any
 * component with a smaller integer. If the integers are the same, the alphabetic sequences are
 * compared lexicographically, and if <i>they</i> turn out to be the same, the final (optional)
 * integer is compared. As with the leading integer, this final integer is considered to be 0 if not
 * present. For example:
 *
 * <pre>
 *   3.1.1 > 3.1.1beta3
 *   3.1.1beta1 > 3.1.0
 *   3.1 > 3.1.0alpha1
 *
 *   3.1.0beta0 > 3.1.0alpha5.6
 *   3.4.2alpha2 > 3.4.2alpha1
 *   3.4.2alpha2 > 3.4.2alpha1.5
 *   3.1alpha1 > 3.1alpha
 * </pre>
 *
 * <p>This class is immutable and can safely be shared among threads.
 */
@Immutable
@AutoCodec
public final class DottedVersion implements DottedVersionApi<DottedVersion> {
  /** Wrapper class for {@link DottedVersion} whose {@link #equals(Object)} method is string
   * equality.
   *
   * <p>This is necessary because Bazel assumes that
   * {@link com.google.devtools.build.lib.analysis.config.FragmentOptions} that are equal yield
   * fragments that are the same. However, this does not hold if the options hold a
   * {@link DottedVersion} because trailing zeroes are not considered significant when comparing
   * them, but they do matter in configuration fragments (for example, they end up in output
   * directory names)</p>
   * */
  @Immutable
  public static final class Option {
    private final DottedVersion version;

    private Option(DottedVersion version) {
      this.version = Preconditions.checkNotNull(version);
    }

    public DottedVersion get() {
      return version;
    }

    @Override
    public int hashCode() {
      return version.stringRepresentation.hashCode();
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }

      if (!(o instanceof Option)) {
        return false;
      }

      return version.stringRepresentation.equals(((Option) o).version.stringRepresentation);
    }
  }

  public static DottedVersion maybeUnwrap(DottedVersion.Option option) {
    return option != null ? option.get() : null;
  }

  public static Option option(DottedVersion version) {
    return version == null ? null : new Option(version);
  }
  private static final Splitter DOT_SPLITTER = Splitter.on('.');
  private static final Pattern COMPONENT_PATTERN =
      Pattern.compile("(\\d+)([a-z0-9]*?)?(\\d+)?", Pattern.CASE_INSENSITIVE);
  private static final String ILLEGAL_VERSION =
      "Dotted version components must all be of the form \\d+([a-z0-9]*?)?(\\d+)? but got %s";
  private static final String NO_ALPHA_SEQUENCE = null;
  private static final Component ZERO_COMPONENT = new Component(0, NO_ALPHA_SEQUENCE, 0, "0");

  /** Exception thrown when parsing an invalid dotted version. */
  public static class InvalidDottedVersionException extends Exception {
    InvalidDottedVersionException(String msg) {
      super(msg);
    }

    InvalidDottedVersionException(String msg, Throwable cause) {
      super(msg, cause);
    }
  }

  /**
   * Create a dotted version by parsing the given version string. Throws an unchecked exception if
   * the argument is malformed.
   */
  public static DottedVersion fromStringUnchecked(String version) {
    try {
      return fromString(version);
    } catch (InvalidDottedVersionException e) {
      throw new IllegalArgumentException(e);
    }
  }

  /**
   * Generates a new dotted version from the given version string.
   *
   * @throws InvalidDottedVersionException if the passed string is not a valid dotted version
   */
  public static DottedVersion fromString(String version) throws InvalidDottedVersionException {
    if (Strings.isNullOrEmpty(version)) {
      throw new InvalidDottedVersionException(String.format(ILLEGAL_VERSION, version));
    }
    ArrayList<Component> components = new ArrayList<>();
    for (String component : DOT_SPLITTER.split(version)) {
      components.add(toComponent(component, version));
    }

    int numOriginalComponents = components.size();

    // Remove trailing (but not the first or middle) zero components for easier comparison and
    // hashcoding.
    for (int i = components.size() - 1; i > 0; i--) {
      if (components.get(i).equals(ZERO_COMPONENT)) {
        components.remove(i);
      } else {
        break;
      }
    }

    return new DottedVersion(ImmutableList.copyOf(components), version, numOriginalComponents);
  }

  private static Component toComponent(String component, String version)
      throws InvalidDottedVersionException {
    Matcher parsedComponent = COMPONENT_PATTERN.matcher(component);
    if (!parsedComponent.matches()) {
      throw new InvalidDottedVersionException(String.format(ILLEGAL_VERSION, version));
    }

    int firstNumber;
    String alphaSequence = NO_ALPHA_SEQUENCE;
    int secondNumber = 0;
    firstNumber = parseNumber(parsedComponent, 1, version);

    if (!Strings.isNullOrEmpty(parsedComponent.group(2))) {
      alphaSequence = parsedComponent.group(2);
    }

    if (!Strings.isNullOrEmpty(parsedComponent.group(3))) {
      secondNumber = parseNumber(parsedComponent, 3, version);
    }

    return new Component(firstNumber, alphaSequence, secondNumber, component);
  }

  private static int parseNumber(Matcher parsedComponent, int group, String version)
      throws InvalidDottedVersionException {
    int firstNumber;
    try {
      firstNumber = Integer.parseInt(parsedComponent.group(group));
    } catch (NumberFormatException e) {
      throw new InvalidDottedVersionException(String.format(ILLEGAL_VERSION, version), e);
    }
    return firstNumber;
  }

  private final ImmutableList<Component> components;
  private final String stringRepresentation;
  private final int numOriginalComponents;

  @AutoCodec.VisibleForSerialization
  DottedVersion(
      ImmutableList<Component> components, String stringRepresentation, int numOriginalComponents) {
    this.components = components;
    this.stringRepresentation = stringRepresentation;
    this.numOriginalComponents = numOriginalComponents;
  }

  @Override
  public int compareTo(DottedVersion other) {
    int maxComponents = Math.max(components.size(), other.components.size());
    for (int componentIndex = 0; componentIndex < maxComponents; componentIndex++) {
      Component myComponent = getComponent(componentIndex);
      Component otherComponent = other.getComponent(componentIndex);
      int comparison = myComponent.compareTo(otherComponent);
      if (comparison != 0) {
        return comparison;
      }
    }
    return 0;
  }

  @Override
  public int compareTo_skylark(DottedVersion other) {
    return compareTo(other);
  }

  /**
   * Returns the string representation of this dotted version, padded or truncated to the specified
   * number of components.
   *
   * <p>For example, a dotted version of "7.3.0" will return "7" if one is requested, "7.3" if two
   * are requested, "7.3.0" if three are requested, and "7.3.0.0" if four are requested.
   *
   * @param numComponents a positive number of dot-separated numbers that should be present in the
   *     returned string representation
   */
  public String toStringWithComponents(int numComponents) {
    Preconditions.checkArgument(numComponents > 0,
        "Can't serialize as a version with %s components", numComponents);
    ImmutableList.Builder<Component> stringComponents = ImmutableList.builder();
    if (numComponents <= components.size()) {
      stringComponents.addAll(components.subList(0, numComponents));
    } else {
      stringComponents.addAll(components);
      for (int i = components.size(); i < numComponents; i++) {
        stringComponents.add(ZERO_COMPONENT);
      }
    }
    return Joiner.on('.').join(stringComponents.build());
  }

  /**
   * Returns the string representation of this dotted version, padded to a minimum number of
   * components if the string representation does not already contain that many components.
   *
   * <p>For example, a dotted version of "7.3" will return "7.3" with either one or two components
   * requested, "7.3.0" if three are requested, and "7.3.0.0" if four are requested.
   *
   * <p>Trailing zero components at the end of a string representation will not be removed. For
   * example, a dotted version of "1.0.0" will return "1.0.0" if only one or two components are
   * requested.
   *
   * @param numMinComponents the minimum number of dot-separated numbers that should be present in
   *     the returned string representation
   */
  public String toStringWithMinimumComponents(int numMinComponents) {
    return toStringWithComponents(Math.max(this.numOriginalComponents, numMinComponents));
  }

  /**
   * Returns true if this version number has any alphabetic characters, such as 'alpha' in
   * "7.3alpha.2".
   */
  public boolean hasAlphabeticCharacters() {
    for (Component component : components) {
      if (!Objects.equals(component.alphaSequence, NO_ALPHA_SEQUENCE)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Returns the number of components in this version number. For example, "7.3.0" has three
   * components.
   */
  public int numComponents() {
    return components.size();
  }

  @Override
  public String toString() {
    return stringRepresentation;
  }

  @Override
  public boolean equals(Object other) {
    if (this == other) {
      return true;
    }
    if (other == null || getClass() != other.getClass()) {
      return false;
    }

    return compareTo((DottedVersion) other) == 0;
  }

  @Override
  public int hashCode() {
    return Objects.hash(components);
  }

  private Component getComponent(int groupIndex) {
    if (components.size() > groupIndex) {
      return components.get(groupIndex);
    }
    return ZERO_COMPONENT;
  }

  @Override
  public void repr(SkylarkPrinter printer) {
    printer.append(stringRepresentation);
  }

  @AutoCodec.VisibleForSerialization
  @AutoCodec
  static final class Component implements Comparable<Component> {
    private final int firstNumber;
    @Nullable private final String alphaSequence;
    private final int secondNumber;
    private final String stringRepresentation;

    @AutoCodec.VisibleForSerialization
    Component(
        int firstNumber,
        @Nullable String alphaSequence,
        int secondNumber,
        String stringRepresentation) {
      this.firstNumber = firstNumber;
      this.alphaSequence = alphaSequence;
      this.secondNumber = secondNumber;
      this.stringRepresentation = stringRepresentation;
    }

    @Override
    public int compareTo(Component other) {
      return ComparisonChain.start()
          .compare(firstNumber, other.firstNumber)
          .compare(alphaSequence, other.alphaSequence, Ordering.natural().nullsLast())
          .compare(secondNumber, other.secondNumber)
          .result();
    }

    @Override
    public boolean equals(Object other) {
      if (this == other) {
        return true;
      }
      if (other == null || getClass() != other.getClass()) {
        return false;
      }

      return compareTo((Component) other) == 0;
    }

    @Override
    public int hashCode() {
      return Objects.hash(firstNumber, alphaSequence, secondNumber);
    }

    @Override
    public String toString() {
      return stringRepresentation;
    }
  }
}
