// 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.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.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
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-z]+\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.
 */
@SkylarkModule(
  name = "DottedVersion",
  category = SkylarkModuleCategory.NONE,
  doc =
      "A value representing a version with multiple components, separated by periods, such as "
          + "1.2.3.4."
)
@Immutable
@AutoCodec
public final class DottedVersion implements Comparable<DottedVersion>, SkylarkValue {
  private static final Splitter DOT_SPLITTER = Splitter.on('.');
  private static final Pattern COMPONENT_PATTERN = Pattern.compile("(\\d+)(?:([a-z]+)(\\d*))?");
  private static final String ILLEGAL_VERSION =
      "Dotted version components must all be of the form \\d+([a-z]+\\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");

  /**
   * Generates a new dotted version from the given version string.
   *
   * @throws IllegalArgumentException if the passed string is not a valid dotted version
   */
  public static DottedVersion fromString(String version) {
    if (Strings.isNullOrEmpty(version)) {
      throw new IllegalArgumentException(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) 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);
      }
    }

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

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

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

    if (parsedComponent.group(2) != null) {
      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) {
    int firstNumber;
    try {
      firstNumber = Integer.parseInt(parsedComponent.group(group));
    } catch (NumberFormatException e) {
      throw new IllegalArgumentException(String.format(ILLEGAL_VERSION, version));
    }
    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
  @SkylarkCallable(
    name = "compare_to",
    doc =
        "Compares based on most signifigant (first) not-matching version component. "
            + "So, for example, 1.2.3 < 1.2.4"
  )
  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;
  }

  /**
   * 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) {
    ImmutableList.Builder<Component> stringComponents = ImmutableList.builder();
    stringComponents.addAll(components);
    int numComponents = Math.max(this.numOriginalComponents, numMinComponents);
    int zeroesToPad = numComponents - components.size();
    for (int i = 0; i < zeroesToPad; i++) {
      stringComponents.add(ZERO_COMPONENT);
    }
    return Joiner.on('.').join(stringComponents.build());
  }

  /**
   * 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;
    }
  }
}
