from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from guardian.core import ObjectPermissionChecker
from guardian.shortcuts import assign, remove_perm, get_users_with_perms, get_groups_with_perms

try:
    from threading import local
except ImportError:
    from django.utils._threading_local import local
    
_thread_locals = local()

def get_current_user():
    return getattr(_thread_locals, 'user', None)

def protect_models():
    cls_list = ToProtect.get_models()
    if cls_list:
        user = get_current_user()
        for cls in ToProtect.get_models():
                protect_model(cls, user)
    
    
def unprotect_models():
    for cls in ToProtect.get_models():
            unprotect_model(cls)

class ToProtect(object):
    
    @staticmethod
    def get_models():
        if hasattr(ToProtect, 'cls_list'):
            return ToProtect.cls_list
        
        cls_list = []
        for cls_name in settings.USE_GROUP_PERMISSIONS:
            cls_type = ContentType.objects.get(model=cls_name.lower())
            cls_list.append(cls_type.model_class())
        ToProtect.cls_list = cls_list
        
        return cls_list

def protect_model(cls, user):   
    cls.safe_objects.user = user
    cls.safe_objects.check_perm = True
    
    cls.old_save = cls.save
    cls.old_delete = cls.delete
    class_name = cls.__name__.lower()
    cls.save = change_security(class_name)(cls.save)
    cls.delete = change_security(class_name)(cls.delete)    
    
def unprotect_model(cls): 
    if hasattr(cls, 'old_save'):
        cls.save = cls.old_save 
        cls.delete = cls.old_delete 
        del cls.old_save    
        del cls.old_delete
        cls.safe_objects.user = None 
        
def change_security(cls_name):
    def wrapper(func):
        def wrapped(self, *args, **kwargs):                      
                        
            if self.pk and not get_current_user().has_perm('change_%s' % cls_name, self):
                raise AttributeError('User %s is not allowed to change object %s' % (get_current_user(), self))
      
            return func(self, *args, **kwargs)
        return wrapped    
    return wrapper

def set_forbidden_stream(xml, user):
    cls = ContentType.objects.get(model='content')
    cls = cls.model_class()
    
    old_user = cls.safe_objects.user
    obj_list = cls.safe_objects.all()
    
    for elem in xml.xpath('/iri/medias/media'):
        if not obj_list.filter(iri_id=elem.get('id')):
            elem.set('video', settings.FORBIDDEN_STREAM_URL)
    
    cls.safe_objects.user = old_user 
    
    return xml

def add_change_attr(user, obj_list):
    if len(obj_list) == 0:
        return []
    
    model_name = obj_list[0].__class__.__name__.lower()
    ctype = ContentType.objects.get(model=model_name)
    cls = ctype.model_class()
    
    checker = ObjectPermissionChecker(user)
    perm_name = "%s.change_%s" % (cls._meta.app_label, model_name)
        
    for obj in obj_list:
        if checker.has_perm(perm_name, obj):
            obj.change = True
        else:
            obj.change = False
            
    return obj_list      

def assign_object_to_groups(object, read_list, write_list, owner):
    name = object.__class__.__name__.lower()
    
    old_users = get_users_with_perms(object).exclude(id=owner.id)
    old_groups = get_groups_with_perms(object)
    
    for elem in read_list:
        assign('view_%s' % name, elem, object)
        if elem in write_list:
            assign('change_%s' % name, elem, object)
        else:
            remove_perm('change_%s' % name, elem, object)            
                
    def remove_perms(new_list, old_list, obj, name):
        for e in old_list:
            if e not in new_list:
                remove_perm('view_%s' % name, e, obj)
                remove_perm('change_%s' % name, e, obj)
                
    remove_perms(read_list, old_users, object, name)
    remove_perms(read_list, old_groups, object, name)
            
            
def get_perm_form(groups, formset):
    perm_list = [] 
    for group in groups:
        perm_list.append({'share': False, 'perms': 'read', 'group': group.id })
    permission = formset(initial=perm_list)
            
    management_form = permission.management_form
    group_form = zip(permission, groups)
    
    return (management_form, group_form)  
            