from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.core.cache import cache
from guardian.shortcuts import remove_perm, get_users_with_perms, get_groups_with_perms, get_objects_for_user
from cache import get_cached_userlist, cached_assign
from ldt.security import change_security
import types
  
def unprotect_instance(instance):
    if hasattr(instance, 'old_save'):
        instance.save = instance.old_save
        instance.delete = instance.old_delete
        
def protect_instance(instance):
    class_name = instance.__class__.__name__.lower()
    cls = ContentType.objects.get(model=class_name)
    cls = cls.model_class()
    
    save = types.MethodType(change_security('project')(cls.save), instance, cls)
    instance.save = save
    
    delete = types.MethodType(change_security('project')(cls.delete), instance, cls)
    instance.delete = delete
        

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

def use_forbidden_url(content):
    c_cls = ContentType.objects.get(model='content')
    c_cls = c_cls.model_class()
    m_cls = ContentType.objects.get(model='media')
    m_cls = m_cls.model_class()
    
    new_content = c_cls.safe_objects.filter(iri_id=content.iri_id)
    if new_content:
        if new_content[0].media_obj:
            media = m_cls.safe_objects.filter(id=new_content[0].media_obj.id)
            if not media:
                return True
    return False

def add_change_attr(user, obj_list):
    """ 
     Add a change attribute set to True to objects of obj_list
     if permissions change_object is set with respect to user.
    """
    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()
    
    # We don't use obj.values_list('pk', flat=True) because the full queryset will be calculated and used after anyway.
    pk_list = [item.pk for item in obj_list]
    if model_name in [cls_name.lower() for cls_name in settings.USE_GROUP_PERMISSIONS] or model_name == 'group':
        to_check = True
        # Filter SUPER usefull : avoid to load ALL objects. We only check permissions on obj_list's objects
        change_list = get_objects_for_user(user, '%s.change_%s' % (cls._meta.app_label, model_name)).filter(pk__in=pk_list)
    else:
        to_check = False
        
    for obj in obj_list:
        if not to_check or obj in change_list:
            obj.change = True
        else:
            obj.change = False
            
    return obj_list

def assign_perm_to_obj(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:
        cached_assign('view_%s' % name, elem, object)
        if elem in write_list:
            cached_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)
    cache.delete('userlist')           
 
    
def get_userlist(user, filter=None):
    user_list = get_cached_userlist().exclude(id=user.id)
    if filter:
        user_list = user_list.filter(username__icontains=filter)
    elem_list = [{'name': u.username, 'id': u.id, 'type': 'user'} for u in user_list[0:settings.MAX_USERS_SEARCH]]
    return elem_list  

def get_userlist_model(object, owner):
    if hasattr(object, 'is_public') and object.is_public:
        return [None, None]
    
    users = get_users_with_perms(object, attach_perms=True, with_group_users=False)
    groups = get_groups_with_perms(object, attach_perms=True)
    object_name = object.__class__.__name__.lower()
    
    def create_dict (users_or_groups, name, groups=True):
        l = []
        admin_list = []
        
        for elem in users_or_groups.keys():
            if elem == owner:
                continue
                        
            if groups:
                elem_dict = {'name': elem.name, 'type': 'group', 'id': elem.id}
            else:
                elem_dict = {'name': elem.username, 'type': 'user', 'id': elem.id}
            
            for perm in users_or_groups[elem]:
                if perm == 'change_%s' % name:
                    elem_dict['change'] = True
                    admin_list.append(elem_dict)
                    continue
                
            l.append(elem_dict)   
        return l, admin_list
    
    users_list, admin_users = create_dict(users, object_name, False)
    groups_list, admin_groups = create_dict(groups, object_name, True)
    
    return [users_list + groups_list, admin_users + admin_groups]
 
def get_userlist_group(group, user):
    members = group.user_set.all()
    admin = get_users_with_perms(group)

    member_list = []
    for u in members:
        if u == user:
            continue
        u_dict = {'name': u.username, 'id': u.id, 'type': 'user', 'change': False}
        if u in admin:
            u_dict['change'] = True
        member_list.append(u_dict)
        
    admin_list = [{'name': e.username, 'id': e.id, 'type': 'user', 'change': False} for e in admin]
    
    return [member_list, admin_list]
