import functools
import json

from aiokts.util.arguments import check_arguments
from aiokts.web.error import ServerError


def arguments_params(arglist=None):
    if arglist is None:
        arglist = {}

    def _arguments(func):
        @functools.wraps(func)
        async def inner(self):
            if self.request.method == 'GET':
                source = self.request.url.query
            else:
                if self.request.content_type.startswith('application/json'):
                    try:
                        source = await self.request.json()
                    except json.JSONDecodeError:
                        raise ServerError(ServerError.BAD_REQUEST(
                            message='Body must be a valid json'))
                else:
                    source = await self.request.post()
            args = check_arguments(arglist, source, cast_type=True)
            return await func(self, **args)

        inner._has_arguments_ = True
        inner.arglist = arglist
        return inner

    return _arguments


def arguments_params_get(arglist=None):
    if arglist is None:
        arglist = {}

    def _arguments(func):
        @functools.wraps(func)
        def inner(self):
            args = check_arguments(
                arglist, self.request.url.query, cast_type=True)
            return func(self, **args)

        inner._has_arguments_ = True
        inner.arglist = arglist
        return inner

    return _arguments


def arguments_params_post(arglist=None):
    if arglist is None:
        arglist = {}

    def _arguments(func):
        @functools.wraps(func)
        async def inner(self):
            data = await self.request.post()
            args = check_arguments(arglist, data, cast_type=True)
            return await func(self, **args)

        inner._has_arguments_ = True
        inner.arglist = arglist
        return inner

    return _arguments


def arguments_params_json(arglist=None):
    if arglist is None:
        arglist = {}

    def _arguments(func):
        @functools.wraps(func)
        async def inner(self):
            try:
                data = await self.request.json()
            except json.JSONDecodeError:
                raise ServerError(ServerError.BAD_REQUEST(
                    message='Body must be a valid json'))
            args = check_arguments(arglist, data, cast_type=True)
            return await func(self, **args)

        inner._has_arguments_ = True
        inner.arglist = arglist
        return inner

    return _arguments

@@ -275,32 +275,49 @@
 c def inner(self
+, *args, **kwargs
 ):%0A            i
@@ -838,32 +838,40 @@
 t()%0A            
+checked_
 args = check_arg
@@ -902,32 +902,72 @@
 cast_type=True)%0A
+            kwargs.update(checked_args)%0A
             retu
@@ -979,33 +979,42 @@
 ait func(self, *
-*
+args, **kw
 args)%0A%0A        i
@@ -1276,32 +1276,49 @@
   def inner(self
+, *args, **kwargs
 ):%0A            a
@@ -1308,32 +1308,40 @@
 s):%0A            
+checked_
 args = check_arg
@@ -1405,32 +1405,72 @@
 cast_type=True)%0A
+            kwargs.update(checked_args)%0A
             retu
@@ -1476,33 +1476,42 @@
 urn func(self, *
-*
+args, **kw
 args)%0A%0A        i
@@ -1780,32 +1780,49 @@
 c def inner(self
+, *args, **kwargs
 ):%0A            d
@@ -1857,32 +1857,40 @@
 t()%0A            
+checked_
 args = check_arg
@@ -1919,32 +1919,72 @@
 cast_type=True)%0A
+            kwargs.update(checked_args)%0A
             retu
@@ -1996,33 +1996,42 @@
 ait func(self, *
-*
+args, **kw
 args)%0A%0A        i
@@ -2308,16 +2308,33 @@
 ner(self
+, *args, **kwargs
 ):%0A     
@@ -2564,16 +2564,24 @@
         
+checked_
 args = c
@@ -2618,32 +2618,72 @@
 cast_type=True)%0A
+            kwargs.update(checked_args)%0A
             retu
@@ -2703,17 +2703,26 @@
 (self, *
-*
+args, **kw
 args)%0A%0A 

Allow chaining arguments decorators