from npm2exheres.print import print_warn
import os


def exist_exheres(pn, pv):
    exheres_path = '{}/{}-{}.exheres-0'.format(pn, pn, pv)
    return os.path.exists(exheres_path)


def filter_versions(versions, verspec):
    """
    >>> filter_versions(['1.2.2', '1.2.3', '1.2.4', '1.3'], '~>1.2.3')
    ['1.2.3', '1.2.4']
    """
    (min_version, max_version) = verspec_to_minmax(verspec)

    return list(filter(lambda v: lte(v, max_version) and gte(v, min_version),
                       versions))


def gte(this, that):
    """
    >>> gte('1.2.3', None)
    True
    >>> gte('1.3.1', [1,3,0])
    True
    >>> gte('1.3', [1,3,0])
    True
    >>> gte('1.3', (1,3,0))
    False
    """
    if not that:
        return True

    this = list(map(int, this.split('.')))

    while len(this) < 3:
        this.append(0)

    if isinstance(that, list):
        return this >= that
    else:
        return this > list(that)


def lte(this, that):
    """
    >>> lte('1.2.3', None)
    True
    >>> lte('1.2.9', [1,3,0])
    True
    >>> lte('1.3', [1,3,0])
    True
    >>> lte('1.3', (1,3,0))
    False
    """
    if not that:
        return True

    this = list(map(int, this.split('.')))

    while len(this) < 3:
        this.append(0)

    if isinstance(that, list):
        return this <= that
    else:
        return this < list(that)


def valid_licenses():
    return os.listdir('/var/db/paludis/repositories/arbor/licences')


def validate_license(license):
    """
    >>> validate_license('BSD-3')
    True
    >>> validate_license('GPL-3')
    True
    >>> validate_license('MIT')
    True
    >>> validate_license('MIT/X11')
    False
    """
    return license in valid_licenses()


def validate_params(pn, pv, params, messages):
    if not params['licenses']:
        print_warn('{}-{}: missing license'.format(pn, pv), messages)
    else:
        licenses = params['licenses'].split(' ')
        for license in licenses:
            if not validate_license(license):
                print_warn('{}-{}: unknown license {}'.format(pn, pv, license),
                           messages)

    if not params['summary']:
        print_warn('{}-{}: missing summary'.format(pn, pv), messages)
    elif len(params['summary']) > 70:
        print_warn('{}-{}: summary is too long'.format(pn, pv), messages)


def verspec_to_minmax(verspec):
    """
    >>> verspec_to_minmax('~>1.2.3')
    ([1, 2, 3], (1, 3, 0))
    >>> verspec_to_minmax('~>1.2')
    ([1, 2, 0], (2, 0, 0))
    >>> verspec_to_minmax('<1.2.3')
    (None, (1, 2, 3))
    """
    if '&' in verspec:
        [min_v, max_v] = verspec.split('&')
        if '~' in min_v:
            verspec = min_v
        elif '~' in max_v:
            verspec = max_v
        else:
            verspec = ''

    if verspec.startswith('~>'):
        min_v = list(map(int, verspec.lstrip('~>').split('.')))
        max_v = min_v[0:-1]
        max_v[-1] += 1
        min_open = False
        max_open = True
    elif verspec.startswith('='):
        min_v = verspec
        max_v = verspec
    elif verspec.startswith('>'):
        min_v = verspec
        max_v = None
    elif verspec.startswith('<'):
        min_v = None
        max_v = verspec

    if min_v:
        if isinstance(min_v, str):
            min_open = not '=' in min_v
            min_v = list(map(int, min_v.lstrip('>=').split('.')))

        while len(min_v) < 3:
            min_v.append(0)

        if min_open:
            min_v = tuple(min_v)

    if max_v:
        if isinstance(max_v, str):
            max_open = not '=' in max_v
            max_v = list(map(int, max_v.lstrip('<=').split('.')))

        while len(max_v) < 3:
            max_v.append(0)

        if max_open:
            max_v = tuple(max_v)

    return (min_v, max_v)

@@ -44,16 +44,26 @@
 port os%0A
+import re%0A
 %0A%0Adef ex
@@ -2549,27 +2549,389 @@
  2, 3))%0A    
-%22%22%22
+%3E%3E%3E verspec_to_minmax('~%3E1.2.3%7C~%3E1.3')%0A    (%5B1, 2, 3%5D, (2, 0, 0))%0A    %22%22%22%0A    if '%7C' in verspec:%0A        %5Ba, b%5D = verspec.split('%7C')%0A        a = list(map(int, a.lstrip('~%3E').split('.')))%0A        b = list(map(int, b.lstrip('~%3E').split('.')))%0A%0A        assert(a%5B1%5D + 1 == b%5B1%5D)%0A%0A        min_v = a%0A        max_v = tuple(%5Bb%5B0%5D + 1, 0, 0%5D)%0A%0A        return (min_v, max_v)%0A
 %0A    if '&' 

support ~>a.b.c|~>d.e validation