from functools import wraps
from app.Vendor.CustomErrorHandler import CustomErrorHandler
from app.Vendor.Code import Code
from app import dBSession
from aiohttp import web
import cerberus, json

''' 
* 验证输入信息根据字段名
* @param  string name
* @param  dict rules
* @param  string error_msg
* @param  string default
* @return response
'''
async def validateInputByName(request, name, rules, error_msg=None, default=''):
    #不准使用error关键字作为请求参数,请求参数都会被格式化成string，无法使用int去验证
    if name == 'error':
        error = {}
        error['msg'] = '不能使用error关键字作用请求参数'
        error['error_code'] = Code.ERROR
        error['error'] = True
        return error
    v = cerberus.Validator(
        rules, error_handler=CustomErrorHandler(custom_messages=error_msg))
    #v = ObjectValidator(rules)
    #这边修改成json格式接收参数
    if request.method == 'GET':
        reqMultiDictValue = request.query
    if request.method == 'POST':
        if  request.content_type == 'application/json':
            reqMultiDictValue = json.loads(str(await request.content.read(), encoding="utf-8"))
        elif request.content_type == 'application/x-www-form-urlencoded' or request.content_type == 'multipart/form-data':
            reqMultiDictValue = await  request.post()
    requestValue = dict()
    if name in reqMultiDictValue:
        requestValue[name] = reqMultiDictValue[name]
    else:
        requestValue[name] = default
    cookedReqVal = {name: requestValue[name]}
    if (v.validate(cookedReqVal)):  # validate
        return requestValue
    error = {}
    error['msg'] = v.errors
    error['error_code'] = Code.ERROR
    error['error'] = True
    return error


""" 
    验证装饰器 
    @params name 字段名
    @params rules 规则
    @params msg 描述
    @params default 默认值
    @return func|json
"""
def validator(name, rules, msg=None, default=""):
    # 装饰器就是把其他函数作为参数的函数
    def wrappar(func):
        @wraps(func)
        async def inner_wrappar(request, *args, **kwargs):
            #print('%s: something before'%name)
            if msg != None:
                msgVal = {name:msg}
            else:
                msgVal = msg
            error = await validateInputByName(request, name, {name: rules}, msgVal, default)
            if 'error' in error:
                return web.json_response(error)
            if 'params' in kwargs.keys():
                kwargs['params'][name]=error[name]
                kwargs= kwargs['params']
            else:
                kwargs=error
            return await func(request, params=kwargs)
        return inner_wrappar 
    return wrappar


""" 
    事务装饰器,不能用于类方法
    @params func
    @return func|False
"""
def transaction(func):
    @wraps(func)
    def inner_wrappar(*args, **kwargs):
        try:
            #print('something before')
            result = func(*args, **kwargs)
            dBSession.commit()
            #print('something after')
            return result
        except  Exception as e:
            print(e)
            dBSession.rollback()  
            return False
    return inner_wrappar 

""" 
    事务装饰器,用于类方法
    @params func
    @return func|False
"""
def classTransaction(func):
    @wraps(func)
    def wrappar(self, *args, **kwargs):
        try:
            #print('something before')
            result = func(self, *args, **kwargs)
            dBSession.commit()
            #print('something after')
            return result
        except  Exception as e:
            print(e)
            dBSession.rollback()  
            return False
    return wrappar 