import functools
import inspect
from distutils.version import LooseVersion

from .enums import HDRSeverity
from .errors.common import InvalidVersion


def compare_version(v1, v2):
    s1 = LooseVersion(v1)
    s2 = LooseVersion(v2)
    if s1 == s2:
        return 0
    elif s1 > s2:
        return -1
    else:
        return 1


def version_lt(v1, v2):
    return compare_version(v1, v2) > 0


def version_gte(v1, v2):
    return not version_lt(v1, v2)


def minimum_version(version):
    def decorator(f):
        @functools.wraps(f)
        def wrapper(self, *args, **kwargs):
            if version_lt(self._server_version, version):
                raise InvalidVersion(
                    '{0} is only available on NETLAB+ systems version {1} or later.'.format(
                        f.__name__, version
                    )
                )
            return f(self, *args, **kwargs)
        return wrapper
    return decorator


def hdr_result(results, severity_level=HDRSeverity.WARN):
    # TODO when card #1109 resolves, include hdr group id in response
    response = {'status': results.get('status_t'), 'value': results.get('value'), 'events': []}
    for event in results.get('events'):
        if event['severity'] <= severity_level.value:
            response['events'].append(event)
    return response


class ParamsMixin:
    def get_params(self):
        frame = inspect.currentframe()
        outer_frames = inspect.getouterframes(frame)
        caller_frame = outer_frames[1][0]

        argvalues = inspect.getargvalues(caller_frame)
        args = argvalues.args
        args.remove('self')
        values = argvalues.locals
        kwargs = argvalues.locals.get('kwargs', dict())

        params = {}
        for arg in args:
            value = values[arg]
            if value is not None:
                params[arg] = value
        params.update(kwargs)
        return params
