/*
 * 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.cassandra.utils;

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

import com.google.common.base.Objects;
import org.apache.commons.lang3.StringUtils;

/**
 * Implements versioning used in Cassandra and CQL.
 * <p>
 * Note: The following code uses a slight variation from the semver document (http://semver.org).
 * </p>
 */
public class CassandraVersion implements Comparable<CassandraVersion>
{
    /**
     * note: 3rd group matches to words but only allows number and checked after regexp test.
     * this is because 3rd and the last can be identical.
     **/
    private static final String VERSION_REGEXP = "(\\d+)\\.(\\d+)(?:\\.(\\w+))?(\\-[.\\w]+)?([.+][.\\w]+)?";
    private static final Pattern PATTERN_WHITESPACE = Pattern.compile("\\w+");

    private static final Pattern pattern = Pattern.compile(VERSION_REGEXP);
    private static final Pattern SNAPSHOT = Pattern.compile("-SNAPSHOT");

    public final int major;
    public final int minor;
    public final int patch;

    private final String[] preRelease;
    private final String[] build;

    /**
     * Parse a version from a string.
     *
     * @param version the string to parse
     * @throws IllegalArgumentException if the provided string does not
     *                                  represent a version
     */
    public CassandraVersion(String version)
    {
        String stripped = SNAPSHOT.matcher(version).replaceFirst("");
        Matcher matcher = pattern.matcher(stripped);
        if (!matcher.matches())
            throw new IllegalArgumentException("Invalid version value: " + version);

        try
        {
            this.major = Integer.parseInt(matcher.group(1));
            this.minor = Integer.parseInt(matcher.group(2));
            this.patch = matcher.group(3) != null ? Integer.parseInt(matcher.group(3)) : 0;

            String pr = matcher.group(4);
            String bld = matcher.group(5);

            this.preRelease = pr == null || pr.isEmpty() ? null : parseIdentifiers(stripped, pr);
            this.build = bld == null || bld.isEmpty() ? null : parseIdentifiers(stripped, bld);
        }
        catch (NumberFormatException e)
        {
            throw new IllegalArgumentException("Invalid version value: " + version, e);
        }
    }

    private static String[] parseIdentifiers(String version, String str)
    {
        // Drop initial - or +
        str = str.substring(1);
        String[] parts = StringUtils.split(str, '.');
        for (String part : parts)
        {
            if (!PATTERN_WHITESPACE.matcher(part).matches())
                throw new IllegalArgumentException("Invalid version value: " + version);
        }
        return parts;
    }

    public int compareTo(CassandraVersion other)
    {
        if (major < other.major)
            return -1;
        if (major > other.major)
            return 1;

        if (minor < other.minor)
            return -1;
        if (minor > other.minor)
            return 1;

        if (patch < other.patch)
            return -1;
        if (patch > other.patch)
            return 1;

        int c = compareIdentifiers(preRelease, other.preRelease, 1);
        if (c != 0)
            return c;

        return compareIdentifiers(build, other.build, -1);
    }

    public boolean is30()
    {
        return major == 3 && minor == 0;
    }

    /**
     * Returns a version that is backward compatible with this version amongst a list
     * of provided version, or null if none can be found.
     * <p>
     * For instance:
     * "2.0.0".findSupportingVersion("2.0.0", "3.0.0") == "2.0.0"
     * "2.0.0".findSupportingVersion("2.1.3", "3.0.0") == "2.1.3"
     * "2.0.0".findSupportingVersion("3.0.0") == null
     * "2.0.3".findSupportingVersion("2.0.0") == "2.0.0"
     * "2.1.0".findSupportingVersion("2.0.0") == null
     * </p>
     */
    public CassandraVersion findSupportingVersion(CassandraVersion... versions)
    {
        for (CassandraVersion version : versions)
        {
            if (isSupportedBy(version))
                return version;
        }
        return null;
    }

    public boolean isSupportedBy(CassandraVersion version)
    {
        return version != null && major == version.major && this.compareTo(version) <= 0;
    }

    private static int compareIdentifiers(String[] ids1, String[] ids2, int defaultPred)
    {
        if (ids1 == null)
            return ids2 == null ? 0 : defaultPred;
        else if (ids2 == null)
            return -defaultPred;

        int min = Math.min(ids1.length, ids2.length);
        for (int i = 0; i < min; i++)
        {
            Integer i1 = tryParseInt(ids1[i]);
            Integer i2 = tryParseInt(ids2[i]);

            if (i1 != null)
            {
                // integer have precedence
                if (i2 == null || i1 < i2)
                    return -1;
                else if (i1 > i2)
                    return 1;
            }
            else
            {
                // integer have precedence
                if (i2 != null)
                    return 1;

                int c = ids1[i].compareTo(ids2[i]);
                if (c != 0)
                    return c;
            }
        }

        if (ids1.length < ids2.length)
            return -1;
        if (ids1.length > ids2.length)
            return 1;
        return 0;
    }

    private static Integer tryParseInt(String str)
    {
        try
        {
            return Integer.valueOf(str);
        }
        catch (NumberFormatException e)
        {
            return null;
        }
    }

    @Override
    public boolean equals(Object o)
    {
        if (!(o instanceof CassandraVersion))
            return false;
        CassandraVersion that = (CassandraVersion) o;
        return major == that.major
               && minor == that.minor
               && patch == that.patch
               && Arrays.equals(preRelease, that.preRelease)
               && Arrays.equals(build, that.build);
    }

    @Override
    public int hashCode()
    {
        return Objects.hashCode(major, minor, patch, preRelease, build);
    }

    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
        sb.append(major).append('.').append(minor).append('.').append(patch);
        if (preRelease != null)
            sb.append('-').append(StringUtils.join(preRelease, "."));
        if (build != null)
            sb.append('+').append(StringUtils.join(build, "."));
        return sb.toString();
    }
}
