#!/usr/bin/env python
# -*- coding: utf-8 -*-
from itertools import chain
from django.views.generic.base import View
import django.dispatch, traceback, simplejson as json
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from Model.models import Permissions, Role, Device_User
from Service.CommonService import CommonService
from Service.ModelService import ModelService
from Object.TokenObject import TokenObject
from Object.ResponseObject import ResponseObject

# 创建信号
roles_done = django.dispatch.Signal(providing_args=[])
perms_done = django.dispatch.Signal(providing_args=[])
rmanger_done = django.dispatch.Signal(providing_args=[])


class Roles(object):
    '''
    role Manager Class
    '''
    try:
        rid = []
        rolename = []
        roles = Role.objects.all()
        for role in roles:
            rolename.append(role.roleName)
            rid.append(role.rid)
    except Exception as e:
        pass

    def __init__(self):
        '''
        信号监听, 注册信号
        Signal.connect(receiver, sender=None, weak=True, dispatch_uid=None)
        receiver: 信号接受者，回调函数
        sender: 信号发送者
        '''
        roles_done.connect(self.callback)

        self.startSignal()

    def callback(self, sender, **kwargs):
        '''
        开启监听之后，就要去实现回调函数了, 注册信号
        :param sender:
        :param kwargs:
        :return:
        '''
        Roles.rid = []
        Roles.rolename = []
        Roles.roles = Role.objects.all()

        for role in Roles.roles:
            Roles.rolename.append(role.roleName)
            Roles.rid.append(role.rid)

    def startSignal(self):
        '''
        触发信号
        指定信号发送者
        :return:
        '''
        roles_done.send(sender=self.__class__)

    def toJSON(self, QuerySets, fields=None, exclude=None):
        listSets = []
        for QuerySet in QuerySets:
            data = {}
            opts = QuerySet._meta
            for f in chain(opts.concrete_fields, opts.private_fields, opts.many_to_many):
                if not getattr(f, 'editable', False):
                    continue
                if fields and f.name not in fields:
                    continue
                if exclude and f.name in exclude:
                    continue
                data[f.name] = f.value_from_object(QuerySet)
            listSets.append(data)
        return listSets

    def queryAllRoles(self, rolenames=None, exclude=None, response=ResponseObject()):
        roles = []
        for role in chain(Roles.roles):
            if rolenames and role.roleName not in rolenames:
                continue
            if exclude and role.roleName in exclude:
                continue
            roles.append(role)
        if len(roles) > 0:
            resultDict = CommonService.qs_to_dict(roles)
            for k, v in enumerate(resultDict["datas"]):
                if len(v['fields']['permission']) > 0:
                    resultDict["datas"][k]['fields']['permissionJson'] = {}
                    for pid in v['fields']['permission']:
                        permission_query_set = Permissions.objects.get(id=pid)
                        resultDict["datas"][k]['fields']['permissionJson'][pid] = permission_query_set.permName
            return response.json(0, resultDict)

        else:
            return response.json(0, {})

    def addRoles(self, content=None, response=ResponseObject()):
        try:
            roleContent = json.loads(content)
        except Exception as e:
            return response.json(444, repr(e))
        else:
            rid = roleContent.get('rid', None)
            if rid == None:
                return response.json(444,'rid')
            try:
                if rid in chain(Roles.rid):
                    return response.json(174)

                permission_list = roleContent['permission']
                roleContent.pop('permission')
                role = Role(**roleContent)
                role.save()
                if len(permission_list) > 0:
                    role.permission.add(*permission_list)
            except Exception as e:
                return response.json(178, repr(e))
            else:
                self.startSignal()
                return response.json(0)

    def delRoles(self, rid=None, rolename=None, response=ResponseObject()):
        if rid != None:
            if rid not in Roles.rid:
                return response.json(173)

            try:
                roletuple = Role.objects.filter(rid=rid).delete()
            except Exception as e:
                return response.json(176, repr(e))
            else:
                if roletuple[0] == 1:
                    self.startSignal()
                    return self.queryAllRoles(response=response)
                else:
                    return response.json(178, {'error_msg': roletuple})
        elif rolename != None:
            if rid not in Roles.rolename:
                return response.json(173)
            try:
                roletuple = Role.objects.filter(roleName=rolename).delete()
            except Exception as e:
                return response.json(176)
            else:
                if roletuple[0] == 1:
                    self.startSignal()
                    return self.queryAllRoles(response=response)
                else:
                    return response.json(178)

    def modifyRoles(self, rid=None, content=None, response=ResponseObject()):
        if rid not in Roles.rid:
            return response.json(173)
        try:
            roleContent = json.loads(content)
        except Exception as e:
            errorInfo = traceback.format_exc()
            print('The content parameter format is wrong: %s' % errorInfo)
            return response.json(444)
        else:
            try:
                permission_list = roleContent['permission']
                roleContent.pop('permission')
                roleCount = Role.objects.filter(rid=rid).update(**roleContent)
                if roleCount:
                    if len(permission_list) > 0:
                        Role.objects.get(rid=rid).permission.set(permission_list)
                    else:
                        Role.objects.get(rid=rid).permission.clear()
            except Exception as e:
                return response.json(177)

            else:
                if roleCount == 1:
                    self.startSignal()
                    return self.queryAllRoles(response=response)
                else:
                    return response.json(177)


class Permission(object):
    try:
        id = []
        permname = []
        perms = Permissions.objects.all()
        for perm in perms:
            id.append(perm.id)
            permname.append(perm.permName)
    except Exception as e:
        pass

    def __init__(self):
        perms_done.connect(self.callback)

        self.startSignal()

    def callback(self, sender, **kwargs):
        Permission.id = []
        Permission.permname = []
        Permission.roles = Permissions.objects.all()

        for perm in Permission.roles:
            Permission.id.append(perm.id)
            Permission.permname.append(perm.permName)

    def startSignal(self):
        perms_done.send(sender=self.__class__)

    def queryAllPerms(self, perms=None, exclude=None, response=ResponseObject()):
        opts = []
        for perm in chain(Permission.permname):
            if perms and perm not in perms:
                continue
            if exclude and perm in exclude:
                continue
            opts.append(perm)
        return response.json(0, {'perms': opts})

    def delPerms(self, id=None, permName=None, response=ResponseObject()):
        if id != None:
            perm = Permissions.objects.filter(id=id)
        elif permName != None:
            perm = Permissions.objects.filter(permName=permName)
        else:
            return response.json(444, 'id,perm')
        if not perm:
            return response.json(173)
        try:
            perm.delete()
        except Exception as e:
            return response.json(176, repr(e))
        else:
            self.startSignal()
            qs = Permissions.objects.all()
            res = CommonService.qs_to_dict(qs)
            return response.json(0, res)

    @staticmethod
    def getAllPermission(response=ResponseObject()):
        send_dict = CommonService.qs_to_dict(Permissions.objects.all())
        return response.json(0, send_dict)


class permManager(object):

    def queryMoreRole(self, rid=None):
        role = Role.objects.filter(rid=rid)
        if not role:
            roleDict = {'rid': role[0].rid, 'error_msg': u'The rid does not exist!'}
            return roleDict
        roleDict = {'rid': role[0].rid, 'perms': role[0].get_all_permission()}
        return roleDict

    def queryAllRole(self, response=ResponseObject()):
        qs = Role.objects.all()
        res = CommonService.qs_to_dict(qs)
        return response.json(0, res)


# 角色View
class queryRoleView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super(queryRoleView, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        request.encoding = 'gb2312'
        token = request.GET.get('token', None)
        return self.ValidationError(token)

    def post(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        token = request.POST.get('token', None)
        return self.ValidationError(token)

    def ValidationError(self, token):
        response = ResponseObject()
        tko = TokenObject(token)
        response.lang = tko.lang
        if tko.code != 0:
            return response.json(tko.code)
        userID = tko.userID
        if userID:
            return self.queryUserRole(userID, response)
        else:
            return response.json(309)

    def queryUserRole(self, userID, response):
        eUser = Device_User.objects.filter(userID=userID)
        if not eUser:
            return response.json(102)
        if 100 in eUser[0].get_role_id():
            role = Roles()
            return role.queryAllRoles(response=response)
        own_permission = ModelService.check_perm(userID=userID, permID=30)
        if own_permission is not True:
            return response.json(404)
        role = Roles()
        return role.queryAllRoles(response=response)


class addNewRoleView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super(addNewRoleView, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        request.encoding = 'gb2312'
        request_dict = request.GET
        return self.ValidationError(request_dict)

    def post(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        request_dict = request.POST
        return self.ValidationError(request_dict)

    def ValidationError(self, request_dict):
        token = request_dict.get('token', None)
        content = request_dict.get('content', None)
        response = ResponseObject()
        if not content:
            return response.json(444, 'content')
        tko = TokenObject(token)
        response.lang = tko.lang
        if tko.code != 0:
            return response.json(tko.code)
        userID = tko.userID
        if not userID:
            return response.json(309)
        return self.AddNewUserRole(userID, content, response)

    def AddNewUserRole(self, userID, content, response):
        User = Device_User.objects.filter(userID=userID)

        rids = User[0].get_role_id()
        if rids == None:
            return response.json(174)
        Aperms = False
        for rid in rids:
            if rid < 10:
                continue
            else:
                Aperms = True
        if not Aperms:
            return response.json(404)
        role = Roles()
        return role.addRoles(content=content, response=response)


class delRoleView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super(delRoleView, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        request.encoding = 'gb2312'
        request_dict = request.GET
        return self.ValidationError(request_dict)

    def post(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        request_dict = request.POST
        return self.ValidationError(request_dict)

    def ValidationError(self, request_dict):
        token = request_dict.get('token', None)
        rid = request_dict.get('rid', None)
        response = ResponseObject()
        if not rid:
            return response.json(444, 'rid')
        tko = TokenObject(token)
        response.lang = tko.lang
        if tko.code != 0:
            return response.json(tko.code)
        userID = tko.userID
        if not userID:
            return response.json(104)
        return self.delRole(userID, int(rid), response)

    def delRole(self, userID, rid, response):
        own_permission = ModelService.check_perm(userID=userID, permID=10)
        if own_permission is not True:
            return response.json(404)
        role = Roles()
        return role.delRoles(rid=rid, response=response)


class modifyRoleView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super(modifyRoleView, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        request_dict = request.GET
        return self.ValidationError(request_dict)

    def post(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        request_dict = request.POST
        return self.ValidationError(request_dict)

    def ValidationError(self, request_dict):
        token = request_dict.get('token', None)
        rid = request_dict.get('rid', None)
        content = request_dict.get('content', None)
        response = ResponseObject()
        if not content or not rid:
            return response.json(444, 'rid,content')
        tko = TokenObject(token)
        response.lang = tko.lang
        if tko.code != 0:
            return response.json(tko.code)
        userID = tko.userID
        if not userID:
            return response.json(104)
        return self.modifyRole(userID, int(rid), content, response)

    def modifyRole(self, userID, rid, content, response):
        User = Device_User.objects.filter(userID=userID)
        rids = User[0].get_role_id()
        if rids == None:
            return response.json(174)
        Aperms = False
        for rrid in rids:
            if rrid < 10:
                continue
            else:
                Aperms = True
        if not Aperms:
            return response.json(404)
        role = Roles()
        return role.modifyRoles(rid=rid, content=content, response=response)


# 权限View
class addNewPermsView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super(addNewPermsView, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        request_dict = request.GET
        return self.ValidationError(request_dict)

    def post(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        request_dict = request.POST
        return self.ValidationError(request_dict)

    def ValidationError(self, request_dict):
        response = ResponseObject()
        token = request_dict.get('token', None)
        tko = TokenObject(token)
        response.lang = tko.lang
        if tko.code != 0:
            return response.json(tko.code)
        userID = tko.userID
        if not userID:
            return response.json(104)
        return self.addNewPermission(userID, request_dict, response)

    def addNewPermission(self, userID, request_dict, response):
        own_perm = ModelService.check_perm(userID, 40)
        if own_perm is not True:
            return response.json(404)
        else:
            add_dict = {
                'id': int(request_dict['id']),
                'permName': request_dict['permName'],
                'description': request_dict['description']}
            try:
                perm = Permissions(**add_dict)
                perm.save()
            except Exception as e:
                return response.json(178, repr(e))
            else:
                return Permission.getAllPermission(response=response)


class delPermsView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super(delPermsView, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        request_dict = request.GET
        return self.ValidationError(request_dict)

    def post(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        request_dict = request.POST
        return self.ValidationError(request_dict)

    def ValidationError(self, request_dict):
        token = request_dict.get('token', None)
        id = request_dict.get('id', None)
        response = ResponseObject()
        if not id:
            return response.json(444, 'id')
        tko = TokenObject(token)
        response.lang = tko.lang
        if tko.code != 0:
            return response.json(tko.code)
        userID = tko.userID
        if not userID:
            return response.json(104)
        return self.delPerms(userID, id, response)

    def delPerms(self, userID, id, response):
        User = Device_User.objects.filter(userID=userID)
        rids = User[0].get_role_id()
        if len(rids) == 0:
            return response.json(174)
        Aperms = False
        for rid in rids:
            if rid < 10:
                continue
            else:
                Aperms = True
        if not Aperms:
            return response.json(404)
        perms = Permission()
        return perms.delPerms(id=id, response=response)


class queryPermsView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super(queryPermsView, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        request_dict = request.GET
        return self.ValidationError(request_dict)

    def post(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        request_dict = request.POST
        return self.ValidationError(request_dict)

    def ValidationError(self, request_dict):
        token = request_dict.get('token', None)
        type = request_dict.get('type', None)

        response = ResponseObject()
        tko = TokenObject(token)
        response.lang = tko.lang
        if tko.code != 0:
            return response.json(tko.code)
        userID = tko.userID
        if not userID:
            return response.json(104)
        if type == 'PC':
            return self.querAllPermission(userID, response)
        else:
            return self.delPerms(userID, response)

    def querAllPermission(self, userID, response):
        own_perm = ModelService.check_perm(userID, 30)
        if own_perm is not True:
            return response.json(404)
        qs = Permissions.objects.all()
        res = CommonService.qs_to_dict(qs)
        return response.json(0, res)

    def delPerms(self, userID, response):
        User = Device_User.objects.filter(userID=userID)
        rids = User[0].get_role_id()
        if len(rids) == 0:
            return response.json(174)
        Aperms = False
        for rid in rids:
            if rid < 10:
                continue
            else:
                Aperms = True
        if not Aperms:
            return response.json(404)
        perms = Permission()
        return perms.queryAllPerms(response=response)


class modifyPermsView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super(modifyPermsView, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        request_dict = request.GET
        return self.ValidationError(request_dict)

    def post(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        request_dict = request.POST
        return self.ValidationError(request_dict)

    def ValidationError(self, request_dict):
        token = request_dict.get('token', None)
        response = ResponseObject()
        tko = TokenObject(token)
        response.lang = tko.lang
        if tko.code != 0:
            return response.json(tko.code)
        userID = tko.userID
        if userID:
            update_dict = {'permName': request_dict['permName'], 'description': request_dict['description']}
            return self.modifyPerms(userID=userID, id=request_dict['id'], update_dict=update_dict,
                                    response=response)
        else:
            return response.json(309)

    def modifyPerms(self, userID, id, update_dict, response):
        try:
            User = Device_User.objects.filter(userID=userID)
        except Exception as e:
            return response.json(500, repr(e))
        else:
            rids = User[0].get_role_id()
            if len(rids) == 0:
                return response.json(174)
            Aperms = False
            for rid in rids:
                if rid < 10:
                    continue
                else:
                    Aperms = True
            if not Aperms:
                return response.json(404)
            try:
                Permissions.objects.filter(id=int(id)).update(**update_dict)
            except Exception as e:
                return response.json(500, repr(e))
            else:
                return Permission.getAllPermission(response=response)


class queryRolePermsView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super(queryRolePermsView, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        request.encoding = 'gb2312'

        token = request.GET.get('token', None)
        allUser = request.GET.get('allUser', False)

        return self.ValidationError(token, allUser)

    def post(self, request, *args, **kwargs):
        request.encoding = 'utf-8'

        token = request.POST.get('token', None)
        allUser = request.POST.get('allUser', False)

        return self.ValidationError(token, allUser)

    def ValidationError(self, token, allUser):
        response = ResponseObject()
        tko = TokenObject(token)
        response.lang = tko.lang
        if tko.code != 0:
            return response.json(tko.code)
        userID = tko.userID
        if userID:
            return self.queryRolePerms(userID, allUser, response)
        else:
            return response.json(309)

    def queryRolePerms(self, userID, allUser, response):
        dUser = Device_User.objects.filter(userID=userID).order_by('-data_joined')
        if not dUser:
            return response.json(104)
        if allUser == '0' or allUser == 'False' or allUser == 'false':
            allUser = False
        elif allUser == '1' or allUser == 'True' or allUser == 'true':
            allUser = True
        else:
            allUser = False
        pM = permManager()
        if not allUser:
            ridslist = []
            rids = dUser[0].get_role_id()

            for rid in rids:
                ridslist.append(pM.queryMoreRole(rid=rid))
            sqlDict = dict(zip(["datas"], [ridslist]))
            return response.json(0, sqlDict)
        else:
            if 100 in dUser[0].get_role_id():
                return pM.queryAllRole(response=response)
            else:
                return response.json(404)
