#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
    对软件版本号进行对比
"""

import re


class VersionComparator(object):

    reg_digit_and_letter = re.compile("^\\d*[a-zA-Z]+$")

    reg_letter = "[a-zA-Z]"

    @staticmethod
    def is_early_than_target_version(current_version, target_version):
        """
        @summary: 对服务器版本号进行对比
        @param current_version : 当前版本号
        @param target_version : 目标版本号
        """
        return VersionComparator.compare_version(current_version, target_version) < 0

    @staticmethod
    def compare_version(current_version, target_version):
        """
        @summary: 大于0代表当前的版本大于目标版本，等于0则相等，小于0则当前版本小于目标版本
        @param current_version : 当前版本号
        @param target_version : 目标版本号
        """
        if current_version == target_version:
            return 0

        cur_strings = current_version.split(".")
        tar_strings = target_version.split(".")
        cur_length = len(cur_strings)
        tar_length = len(tar_strings)
        min_length = min(cur_length, tar_length)
        is_cur_version_min_length = min_length == cur_length

        # 如果长度不一致，并且最小长度等于2，那么长度为2的是旧版本
        if min_length == 2 and cur_length != tar_length:
            return -1 if is_cur_version_min_length else 1

        # 如果长度不一致，需要补齐后再对比
        if cur_length != tar_length:
            # 将字符串数组不足的部分全部补为0，当最短为当前版本时，补全当前版本的空余部分
            if is_cur_version_min_length:
                cur_strings = VersionComparator.fill_arrays_length(tar_strings, cur_strings)
            else:
                tar_strings = VersionComparator.fill_arrays_length(cur_strings, tar_strings)

        # 将数组中的所有字符串补齐后，开始逐个比对
        range_num = len(cur_strings)
        for i in range(range_num):
            cur_string = cur_strings[i]
            tar_string = tar_strings[i]

            result = VersionComparator.version_compare_execute(cur_string, tar_string)
            if result != 0:
                return result

        return 0

    @staticmethod
    def fill_arrays_length(strs_max, strs_min):
        """
        @summary: 用0来填充位数少的版本号，直到两个版本号位数一致 例如2.3.0和2.3.0.1，则2.3.0会变成2.3.0.0
        @param current_version : 位数多的版本号
        @param target_version : 位数少的版本号
        """

        min_length = len(strs_min)
        max_length = len(strs_max)

        for i in range(min_length, max_length):
            strs_min[i] = VersionComparator.add_zeros_to_prefix("", len(strs_max[i]))

        return strs_min

    @staticmethod
    def add_zeros_to_prefix(str_need_fill_zeo, zero_num):
        """
        @summary: 用0来填充传入的字符串
        @param str_need_fill_zeo : 需要填充0的字符串
        @param zero_num : 需要在字符串前面填充的0的个数
        """
        if zero_num == 0:
            return str_need_fill_zeo

        str_will_fill_zero = list(str_need_fill_zeo)
        for _ in range(zero_num):
            str_will_fill_zero.insert(0, "0")

        return "".join(str_will_fill_zero)

    @staticmethod
    def fill_and_compare(cur_string, tar_string):
        """
        @summary: 对单个位数上的数字填充并对比，否则无法直接比较大小
        @param current : 当前字符串
        @param target : 目标字符串
        """
        cur_length = len(cur_string)
        tar_length = len(tar_string)

        diff = abs(cur_length - tar_length)

        if cur_length > tar_length:
            tar_string = VersionComparator.add_zeros_to_prefix(tar_string, diff)
        else:
            cur_string = VersionComparator.add_zeros_to_prefix(cur_string, diff)

        if cur_string > tar_string:
            return 1
        elif cur_string < tar_string:
            return -1
        else:
            return 0

    @staticmethod
    def version_compare_execute(current, target):
        """
        @summary: 对单个位数上的数字对比 例如2.3.0中对 2这个号进行对比
        @param current : 当前字符串
        @param target : 目标字符串
        """
        is_current_digit_and_letter = VersionComparator.match_version(current)
        if (current.isdigit() and target.isdigit()) \
                or (is_current_digit_and_letter and VersionComparator.match_version(target)) :
            return VersionComparator.fill_and_compare(current, target)

        '''
        当其中一个含有字母，其中一个不含有字母的时候，
            不仅需要切割有字符的那个然后进行填充对比，当填充对比的结果为相等时，带有字母的那一位版本新一些
        '''
        if is_current_digit_and_letter :
            cur_strings = re.split(VersionComparator.reg_letter, current)
            cur_string = cur_strings[0] if len(cur_strings) == 2 else ""
            result = VersionComparator.fill_and_compare(cur_string, target)
            return 1 if result == 0 else result
        else:
            tar_strings = re.split(VersionComparator.reg_letter, target)
            tar_string = tar_strings[0] if len(tar_strings) == 2 else ""
            result = VersionComparator.fill_and_compare(current, tar_string)
            return -1 if result == 0 else result

    @staticmethod
    def match_version(str_need_match):
        match_result = VersionComparator.reg_digit_and_letter.search(str_need_match)
        return True if match_result else False
