/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.drill.exec.store.parquet.metadata;

import com.google.common.base.Preconditions;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableSortedSet;
import org.apache.drill.common.exceptions.DrillRuntimeException;

import java.util.SortedSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MetadataVersion implements Comparable<MetadataVersion> {

  private static final String FORMAT = "v?((?!0)\\d+)(\\.(\\d+))?";
  private static final Pattern PATTERN = Pattern.compile(FORMAT);

  private final int major;
  private final int minor;

  public MetadataVersion(int major, int minor) {
    this.major = major;
    this.minor = minor;
  }

  public MetadataVersion(String metadataVersion) {
    Matcher matcher = PATTERN.matcher(metadataVersion);
    if (!matcher.matches()) {
      throw DrillRuntimeException.create(
          "Could not parse metadata version '%s' using format '%s'", metadataVersion, FORMAT);
    }
    this.major = Integer.parseInt(matcher.group(1));
    this.minor = matcher.group(3) != null ? Integer.parseInt(matcher.group(3)) : 0;
  }

  public int getMajor() {
    return major;
  }

  public int getMinor() {
    return minor;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof MetadataVersion)) {
      return false;
    }
    MetadataVersion that = (MetadataVersion) o;
    return this.major == that.major
        && this.minor == that.minor;
  }

  @Override
  public int hashCode() {
    int result = major;
    result = 31 * result + minor;
    return result;
  }

  /**
   * @return string representation of the metadata file version, for example: "1", "10", "4.13"
   * <p>
   * String metadata version consists of the following characters:<p>
   * major metadata version (any number of digits, except a single zero digit),<p>
   * optional "." delimiter (used if minor metadata version is specified),<p>
   * minor metadata version (not specified for "0" minor version)
   */
  @Override
  public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append(major);
    if (minor != 0) {
      builder.append(".").append(minor);
    }
    return builder.toString();
  }

  @Override
  public int compareTo(MetadataVersion o) {
    Preconditions.checkNotNull(o);
    return ComparisonChain.start()
        .compare(this.major, o.major)
        .compare(this.minor, o.minor)
        .result();
  }

  /**
   * Check if this version is at least (equals or higher) the one
   * identified by {@code major} and {@code minor} versions integer literals.
   *
   * @param major major version
   * @param minor minor version
   * @return {@literal true} if the version is equal to or higher than
   *         the one it is being checked against
   */
  public boolean isAtLeast(int major, int minor) {
    return this.major > major || (this.major == major && this.minor >= minor);
  }

  /**
   * Check if the version is the same as the one identified by
   * {@code major} and {@code minor} versions integer literals.
   *
   * @param major major version
   * @param minor minor version
   * @return {@literal true} if the version is equal to the one
   *         it is being checked against
   */
  public boolean isEqualTo(int major, int minor) {
    return this.major == major && this.minor == minor;
  }

  /**
   * Check if this version comes after the one identified by {@code major}
   * and {@code minor} versions integer literals. That is, this one was introduced later.
   *
   * @param major major version
   * @param minor minor version
   * @return {@literal true} if the version is defined later than
   *         the one it is being checked against
   */
  public boolean isHigherThan(int major, int minor) {
    return this.major > major || (this.major == major && this.minor > minor);
  }

/**
 * Supported metadata versions.
 * <p>
 * Note: keep them synchronized with {@link org.apache.drill.exec.store.parquet.metadata.MetadataBase.ParquetTableMetadataBase} versions
 */
  public static class Constants {
    /**
     * Version 1: Introduces parquet file metadata caching.<br>
     * See DRILL-2743
     */
    public static final String V1 = "v1";
    /**
     * Version 2: Metadata cache file size is reduced.<br>
     * See DRILL-4053
     */
    public static final String V2 = "v2";
    /**
     * Version 3: Difference between v3 and v2 : min/max, type_length, precision, scale, repetitionLevel, definitionLevel.<br>
     * Filter pushdown for Parquet is implemented. <br>
     * See DRILL-1950
     */
    public static final String V3 = "v3";
    /**
     * Version 3.1: Absolute paths of files and directories are replaced with relative ones. Metadata version value
     * doesn't contain `v` letter<br>
     * See DRILL-3867, DRILL-5660
     */
    public static final String V3_1 = "3.1";

    /**
     * Version 3.2: An array with the components of the field name in
     * {@link org.apache.drill.exec.store.parquet.metadata.Metadata_V3.ColumnTypeMetadata_v3.Key} class is replaced by the {@link org.apache.drill.common.expression.SchemaPath}.<br>
     * See DRILL-4264
     */
    public static final String V3_2 = "3.2";

    /**
     * Version 3.3: Changed serialization of BINARY and FIXED_LEN_BYTE_ARRAY fields.<br>
     * See DRILL-4139
     */
    public static final String V3_3 = "3.3";

    /**
     *  Version 4.0: Split the metadata cache file into summary and file metadata
     */
    public static final String V4 = "4.0";

    /**
     *  Version 4.1: Added parents' original types in {@link Metadata_V4.ColumnTypeMetadata_v4}
     *  and {@link Metadata_V4.ColumnMetadata_v4}
     */
    public static final String V4_1 = "4.1";

    /**
     * Version 4.2: Added {@link org.apache.parquet.schema.Type.Repetition} to {@link Metadata_V4.ColumnTypeMetadata_v4}.
     */
    public static final String V4_2 = "4.2";

    /**
     * All historical versions of the Drill metadata cache files. In case of introducing a new parquet metadata version
     * please follow the {@link MetadataVersion#FORMAT}.
     */
    public static final SortedSet<MetadataVersion> SUPPORTED_VERSIONS = ImmutableSortedSet.of(
        new MetadataVersion(V1),
        new MetadataVersion(V2),
        new MetadataVersion(V3),
        new MetadataVersion(V3_1),
        new MetadataVersion(V3_2),
        new MetadataVersion(V3_3),
        new MetadataVersion(V4),
        new MetadataVersion(V4_1),
        new MetadataVersion(V4_2)
    );

    /**
     * @param metadataVersion string representation of the parquet metadata version
     * @return true if metadata version is supported, false otherwise
     */
    public static boolean isVersionSupported(String metadataVersion) {
      return SUPPORTED_VERSIONS.contains(new MetadataVersion(metadataVersion));
    }
  }
}
