import functools
import threading

from ajunit.suitebuilder import SuiteBuilder


class DecoratorType:

    TEST_SUITE = "testSuite"
    BEFORE_CLASS = "beforeClass"
    BEFORE_TEST = "beforeTest"
    AFTER_TEST = "afterTest"
    AFTER_CLASS = "afterClass"
    TEST_CASE = "testCase"


class Suite(object):

    def __init__(self, **decorator_kwargs):
        self.decorator_kwargs = decorator_kwargs

    def __call__(self, cls):

        SuiteBuilder.build_suite_definitions(decorated_function=cls,
                                             decorator_kwargs=self.decorator_kwargs,
                                             decorator_type=DecoratorType.TEST_SUITE)
        return cls


def test(**decorator_kwargs):
    def decorator(decorated_function):
        def wrapped_function():
            SuiteBuilder.build_suite_definitions(decorated_function=decorated_function,
                                                 decorator_kwargs=decorator_kwargs,
                                                 decorator_type=DecoratorType.TEST_CASE)
        return wrapped_function()
    return decorator


def beforeTest(**decorator_kwargs):
    def decorator(decorated_function):
        def wrapped_function():
            SuiteBuilder.build_suite_definitions(decorated_function=decorated_function,
                                                 decorator_kwargs=decorator_kwargs,
                                                 decorator_type=DecoratorType.BEFORE_TEST)
        return wrapped_function()
    return decorator


def beforeClass(**decorator_kwargs):
    def decorator(decorated_function):
        def wrapped_function():
            SuiteBuilder.build_suite_definitions(decorated_function=decorated_function,
                                                 decorator_kwargs=decorator_kwargs,
                                                 decorator_type=DecoratorType.BEFORE_CLASS)
        return wrapped_function()
    return decorator


def afterTest(**decorator_kwargs):
    def decorator(decorated_function):
        def wrapped_function():
            SuiteBuilder.build_suite_definitions(decorated_function=decorated_function,
                                                 decorator_kwargs=decorator_kwargs,
                                                 decorator_type=DecoratorType.AFTER_TEST)
        return wrapped_function()
    return decorator


def afterClass(**decorator_kwargs):
    def decorator(decorated_function):
        def wrapped_function():
            SuiteBuilder.build_suite_definitions(decorated_function=decorated_function,
                                                 decorator_kwargs=decorator_kwargs,
                                                 decorator_type=DecoratorType.AFTER_CLASS)
        return wrapped_function()
    return decorator


def meta(**decorator_kwargs):
    return decorator_kwargs


def synchronized(lock=threading.Lock()):
    def wrapper(f):
        @functools.wraps(f)
        def inner_wrapper(*args, **kw):
            with lock:
                return f(*args, **kw)
        return inner_wrapper
    return wrapper
