from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import Group
from django.core.files import File
from django.core.urlresolvers import reverse
from django.db import transaction
from django.forms.models import model_to_dict
from django.forms.util import ErrorList
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response, redirect
from django.template import RequestContext
from django.utils.translation import ugettext as _, ungettext
from guardian.shortcuts import remove_perm
from ldt.ldt_utils.forms import ContentForm, MediaForm
from ldt.ldt_utils.models import Content, Media, Project
from ldt.security.cache import cached_assign
from ldt.security.utils import (assign_perm_to_obj, add_change_attr, get_userlist, 
    get_userlist_model)
from ldt.user.forms import PictureForm
from tagging.models import Tag, TaggedItem
import datetime
import ldt.utils.path as ldt_utils_path
import logging
import math
import mimetypes
import os
import re
import requests
import subprocess
import sys
import tempfile
import traceback
import urllib2
import urlparse
#from django.core.files.temp import NamedTemporaryFile

def media_management(request, media_input_type, cleaned_data, content_form, media_form, form_status):
    if media_input_type == "none":
                    media = None
    elif media_input_type == "link":
        media = content_form.cleaned_data["media_obj"]
        created = False
    elif media_input_type == "create":
        del cleaned_data["media_file"]
        if not cleaned_data['videopath']:
            cleaned_data['videopath'] = settings.STREAM_URL
        # if the source is already http:// or rtmp:// we don't have to add STREAM_URL
        if cleaned_data['src'].startswith("rtmp://") or cleaned_data['src'].startswith("http://") or cleaned_data['src'].startswith("https://"):
            cleaned_data['videopath'] = ''
            
            media, created = Media.objects.get_or_create(src=cleaned_data['src'], defaults=cleaned_data) #@UndefinedVariable
    
    elif media_input_type == "url" or media_input_type == "upload" :
        # copy file
        #complet src
        destination_file = None
        source_file = None
        try:
            if media_input_type == "url":
                url = cleaned_data["external_src_url"]
                source_file = urllib2.urlopen(url)
                source_filename = source_file.info().get('Content-Disposition', None)
                if not source_filename:
                    source_filename = urlparse.urlparse(url).path.rstrip("/").split('/')[-1]
            elif media_input_type == "upload":
                #source_file = request.FILES['media-media_file']
                # At this point the file has already be uploaded thanks to the upload view, and original file name is sent through a post var
                source_filename = request.POST["media-local_file_name"]
            
            source_filename = ldt_utils_path.sanitize_filename(source_filename)
            destination_filepath = os.path.join(settings.STREAM_PATH, source_filename)
            base_source_filename = source_filename
            extension = base_source_filename.split(".")[-1]
            if extension == base_source_filename:
                extension = ""
                base_basename_filename = base_source_filename
            else:
                base_basename_filename = base_source_filename[:-1 * (len(extension) + 1)]
            i = 0
            
            while os.path.exists(destination_filepath):
                base_source_filename = "%s.%d.%s" % (base_basename_filename, i, extension)
                destination_filepath = os.path.join(settings.STREAM_PATH, base_source_filename)
                i += 1
            
            if media_input_type == "url":
                # we upload the file if we are in url case
                destination_file = open(destination_filepath, "wb")
                chunck = source_file.read(2048)
                while chunck:
                    destination_file.write(chunck)
                    chunck = source_file.read(2048)
                
            elif media_input_type == "upload":
                # The media file has been uploaded in the session temp folder 
                # so we just have to move to the regular folder and rename it.
                if os.path.exists(os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", source_filename)):
                    os.rename(os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", source_filename), os.path.join(settings.STREAM_PATH, base_source_filename))
            
            
            src_prefix = settings.STREAM_SRC_PREFIX.rstrip("/")
            if len(src_prefix) > 0:
                cleaned_data["src"] = src_prefix + "/" + base_source_filename
            else:
                cleaned_data["src"] = base_source_filename
            
            
        except Exception as inst:
            logging.debug("write_content_base : POST error when processing file:" + str(inst)) #@UndefinedVariable
            form_status = "error"
            #set error for form
            if media_input_type == "url":
                errors = media_form._errors.setdefault("external_src_url", ErrorList())
                errors.append(_("Problem when downloading file from url : ") + url)
            elif media_input_type == "upload":
                errors = media_form._errors.setdefault("media_file", ErrorList())
                errors.append(_("Problem when uploading file : ") + str(inst))
        finally:
            if media_input_type == "url":
                if destination_file:
                    destination_file.close()
                if source_file:
                    source_file.close()
        
        
        if form_status != "error":
            del cleaned_data["media_file"]
            if not cleaned_data['videopath']:
                cleaned_data['videopath'] = settings.STREAM_URL
            mimetype = cleaned_data.get('mimetype_field', None)
            if not mimetype:
                mimetype = mimetypes.guess_type(cleaned_data['src'])
            cleaned_data['mimetype_field'] = mimetype
            media, created = Media.safe_objects.get_or_create(src=cleaned_data['src'], defaults=cleaned_data) #@UndefinedVariable
            cached_assign('view_media', request.user, media)
        else:
            media = None
            

    if media and not created:
        for attribute in ('external_id', 'external_permalink', 'external_publication_url', 'external_src_url', 'media_creation_date', 'videopath', 'duration', 'description', 'title', 'front_project'):
            setattr(media, attribute, cleaned_data.get(attribute))
        mimetype = cleaned_data.get('mimetype_field', None)
        if not mimetype:
            mimetype = mimetypes.guess_type(media.src)
        media.mimetype_field = mimetype
        cached_assign('view_media', request.user, media)
        cached_assign('change_media', request.user, media)
        media.save()
        
    return media, form_status
    
    
@transaction.commit_manually
def write_content_base(request, iri_id=None):
    if iri_id:
        instance_content = Content.safe_objects.get(iri_id=iri_id) #@UndefinedVariable
        instance_media = instance_content.media_obj
        logging.debug("write_content_base : valid form: for instance : media -> " + repr(instance_media) + " content : for instance : " + repr(instance_content)) #@UndefinedVariable
    else:
        logging.debug("No iri_id") #@UndefinedVariable
        instance_content = None
        instance_media = None
    current_front_project = None
    if instance_content:
        current_front_project = instance_content.front_project
    form_status = 'none'
    errors_transaction = []
    
    if request.method == "POST":
        try:
            if instance_content is not None:
                content_instance_val = model_to_dict(instance_content, exclude=ContentForm.Meta.exclude)
            else:
                content_instance_val = {}
            
            if instance_media is not None:
                media_instance_val = model_to_dict(instance_media, exclude=MediaForm.Meta.exclude)
            else:
                media_instance_val = {}
            #add prefix
            
            def add_prefix(_dict, prefix):
                return dict([('%s-%s' % (prefix, key), value) for key,value in _dict.items()])
            
            content_instance_val = add_prefix(content_instance_val, "content")
            media_instance_val= add_prefix(media_instance_val, "media")    
                    
            for k in request.POST.keys():
                value = request.POST.get(k)
                content_instance_val[k] = value
                media_instance_val[k] = value
                
            content_instance_val['read_list'] = request.POST.getlist('read_list')
            content_instance_val['write_list'] = request.POST.getlist('write_list')
            content_instance_val['share'] = request.POST.get('share', True)
            
            content_form = ContentForm(content_instance_val, prefix="content", instance=instance_content)
            media_form = MediaForm(media_instance_val, request.FILES, prefix="media", instance=instance_media)
            picture_form = PictureForm(None, request.POST, request.FILES)
       
            if request.user.is_staff:
                content_form.fields['front_project'].queryset = Project.objects.filter(contents__in=[instance_content])
            
            media_valid = media_form.is_valid()
            content_valid = content_form.is_valid()
            picture_valid = picture_form.is_valid()
            
            if 'image' in request.POST.keys():
                image_link = request.POST.get('url_image')
                if picture_valid and image_link!='' :
                    try :
                        r = requests.get(image_link)
                        img_temp = tempfile.NamedTemporaryFile(suffix='.png')
                        if img_temp:
                            img_temp.write(r.content)
                            img_temp.flush()
                            picture_form.cleaned_data["image"]=File(img_temp) 
                    except Exception as inst:
                        logging.debug("couldn't download video thumbnail from image_link : " + str(image_link))
            logging.debug("write_content_base : valid form: for instance : " + repr(instance_media) + " -> media " + str(media_valid) + " content : for instance : " + repr(instance_content) + " : " + str(content_valid) + "picture : valid :" +str(picture_valid)) #@UndefinedVariable
            
            if media_valid and content_valid and picture_valid:
    
                # see if media must be created
                cleaned_data = {}
                cleaned_data.update(media_form.cleaned_data)
                cleaned_data.pop("media_public")
                
                media_input_type = content_form.cleaned_data["media_input_type"]
                
                
                
                
                media, form_status = media_management(request, media_input_type, cleaned_data, content_form, media_form, form_status)
                
                
                
                
                if form_status != "error": 
                    content_defaults = {}
                    content_defaults.update(content_form.cleaned_data)
                    content_defaults['media_obj'] = media
                                   
                    for key in ["media_input_type", "groups", "is_public", "read_list", "write_list", "share" ]:
                        del content_defaults[key]
                        
                    content, created = Content.safe_objects.get_or_create(iri_id=content_form.cleaned_data['iri_id'], defaults=content_defaults) #@UndefinedVariable
                                      
                    if not created and not request.user.has_perm('ldt_utils.change_content', content):
                        raise AttributeError("%s is not allowed to change content %s" % (request.user, content))
                    
                    cached_assign('change_content', request.user, content)
                    cached_assign('view_content', request.user, content)
                    everyone = Group.objects.get(name=settings.PUBLIC_GROUP_NAME)
                    
                    if media_form.cleaned_data['media_public']:
                        cached_assign('view_content', everyone, content)
                        if media:
                            cached_assign('view_media', everyone, media)
                    else:
                        remove_perm('ldt_utils.view_media', everyone, media)
                        assign_perm_to_obj(content, content_form.cleaned_data['read_list'], content_form.cleaned_data['write_list'], request.user)
                        if media:
                            assign_perm_to_obj(media, content_form.cleaned_data['read_list'], content_form.cleaned_data['write_list'], request.user)
                        if content_form.cleaned_data['is_public']:
                            cached_assign('view_content', everyone, content)
                        else:
                            remove_perm('ldt_utils.view_content', everyone, content)
                    
                    if not created:
                        for attribute in ('iriurl', 'title', 'description', 'duration', 'content_creation_date', 'tags', 'media_obj'):
                            setattr(content, attribute, content_defaults[attribute])
                            
                        if request.user.is_staff and content_defaults.has_key('front_project'):
                            content.front_project = content_defaults['front_project']
                    
                    content.save()
                    picture_form.model = content
                    picture_form.save()  
                    form_status = 'saved'
                    media_form = MediaForm(instance=media, prefix="media")
                    content_form = ContentForm(instance=content, prefix="content")
                    picture_form = PictureForm()
            else:
                form_status = 'error'
        except Exception, e:
            transaction.rollback()
            __, value, traceback = sys.exc_info()
            return False, False, False, False, False, errors_transaction, e, traceback
            
    else:
        form_status = 'empty'
        initial_c = { 'media_input_type':"link"}
        initial_m = {}
        if instance_media:
            initial_m['media_public'] = instance_media.is_public
        else:
            initial_m['media_public'] = True
        if instance_content:
            initial_c['is_public'] = instance_content.is_public
        else:
            initial_c['is_public'] = True
        content_form = ContentForm(prefix="content", instance=instance_content, initial=initial_c)
        media_form = MediaForm(prefix="media", instance=instance_media, initial=initial_m) 
        picture_form = PictureForm() 
                
        if instance_content is not None:
            content_form.media_input_type = "link"
                   
            if request.user.is_staff:
                content_form.fields['front_project'].queryset = Project.objects.filter(contents__in=[instance_content])
    
    try:
        transaction.commit()
    except Exception, e:
        transaction.rollback()
        errors_transaction.append(e)
        type, value, traceback = sys.exc_info()
        return False, False, False, False, False, errors_transaction, e, traceback
        
    return content_form, media_form, picture_form, form_status, current_front_project, errors_transaction, "", ""

@login_required
def write_content(request, iri_id=None):  
    submit_action = request.REQUEST.get("submit_button", False) 
    member_list = admin_list = []
    current_front_project = None
    deleted = None
    
    if submit_action == "prepare_delete":
        errors, titles, message_temp = prepare_delete_content(request, iri_id)
        if errors and len(errors) > 0:
            message = ungettext("There is %(count)d error when deleting content", "There are %(count)d errors when deleting content", len(errors)) % { 'count': len(errors)}
            title_msg = _('title error deleting content')
        else:
            if len(message_temp)>0:
                message = message_temp
            else:    
                message = _("Confirm delete content %(titles)s") % { 'titles' : ",".join(titles) }
            title_msg = _("confirm delete content")
        return render_to_response('ldt/ldt_utils/error_confirm.html', {'errors':errors, 'message':message, 'title': title_msg}, context_instance=RequestContext(request))  
    elif submit_action == "delete":
        deleted, errors_transaction = delete_content(request, iri_id)
        content_form = ContentForm()
        form_status = "deleted"
    elif submit_action == "prepare_reset":
        errors=[]
        content_temp = Content.objects.get(iri_id=iri_id)
        if content_temp.front_project is not None:
            if content_temp.front_project.state==2:
                errors.append(_("Please unpublish the front project %(title)s") % {'title':content_temp.front_project.title})
                message=_("The front project is published")
                title = _("confirm reset")
            else:
                message = _("please confirm reseting project %(title)s") % {'title':content_temp.front_project.title}
                title = _("confirm reset")
        else:
            content_temp.create_front_project()
            return redirect("root-view")
        return render_to_response('ldt/ldt_utils/reset_confirm.html', {'errors':errors, 'message':message, 'title': title}, context_instance=RequestContext(request))
    elif submit_action == "reset":
        #TODO : verifier index de la recherche maj
        content = Content.objects.get(iri_id=iri_id)
        project_temp = content.front_project
        content.create_front_project()
        content.save()
        project_temp.delete()
        return HttpResponseRedirect(reverse('ldt.ldt_utils.views.content.write_content', kwargs={'iri_id':iri_id}))
    elif submit_action=="close":
        return redirect("root-view")
    else:
        content_form, media_form, picture_form, form_status, current_front_project, errors_transaction, e, traceback = write_content_base(request, iri_id)        
        if iri_id:
            content_temp = Content.objects.get(iri_id=iri_id)
            media_temp = content_temp.media_obj
            if media_temp:
                member_list, admin_list = get_userlist_model(media_temp, request.user)
            else:
                member_list, admin_list = get_userlist_model(content_temp, request.user)
    
    # Deleted is False if an error occurred during deletion
    if (deleted == False)  or (content_form == False and media_form == False and picture_form == False and form_status == False and current_front_project == False):
        message=_("An error occurred - Please try again or contact webmaster")
        title = _("Error")
        logging.error(e)
        raise e, None, traceback
    
    if iri_id:
        create_content_action = reverse('ldt.ldt_utils.views.content.write_content', kwargs={'iri_id':iri_id})
        img_container = content_form.instance

    else:
        create_content_action = reverse('ldt.ldt_utils.views.content.write_content')
        img_container = ''
    
    session_key = request.COOKIES[settings.SESSION_COOKIE_NAME]
    cookie_name = settings.SESSION_COOKIE_NAME
    # Media.safe_objects.all() does not return the good list of media, so we get them from the Content.safe_objects
    content_form.fields["media_obj"].queryset = Media.objects.filter(id__in=Content.safe_objects.values_list('media_obj', flat=True))
    
    if form_status=='saved' or form_status=='deleted':
        return redirect("root-view") 
    else:
        group_list = Group.objects.all()
        group_list = group_list.exclude(name=settings.PUBLIC_GROUP_NAME)
        group_list = [{'name': u.name, 'id': u.id, 'type': 'group'} for u in group_list[0:settings.MAX_USERS_SEARCH]]
        elem_list = get_userlist(request.user) + group_list
        return render_to_response('ldt/ldt_utils/create_content.html', {'content_form': content_form, 'media_form': media_form, 'form_status': form_status, 'create_content_': create_content_action,
                                                                    'elem_list':elem_list, 'member_list': member_list, 'admin_list': admin_list,  'iri_id': iri_id, 'session_key':session_key,
                                                                    'cookie_name':cookie_name, 'img_container': img_container, 'profile_picture_form': picture_form,
                                                                    'current_front_project':current_front_project}, context_instance=RequestContext(request))
@login_required
def prepare_delete_content(request, iri_id=None): 
    errors = []
    titles = []
    message={}
    if not iri_id:
        iri_id = request.REQUEST.get("iri_id", None)
        
    if iri_id:
        for content in Content.safe_objects.filter(iri_id=iri_id): 
            titles.append(unicode(content.title))
            projects = content.project_set.all()
            projects_nb = len(projects)
            if projects_nb > 1:
                project_titles = map(lambda p: unicode(p.title), projects)
                errors.append(ungettext("Content '%(title)s' is referenced by this project : %(project_titles)s. Please delete it beforehand.", "Content '%(title)s' is referenced by %(count)d projects: %(project_titles)s. Please delete them beforehand.", projects_nb) % {'title':unicode(content.title), 'count':projects_nb, 'project_titles': ",".join(project_titles)})
            elif projects_nb == 1:
                if projects[0].has_annotations():
                    message = _("The project '%(project_title)s' pointing on the content '%(title)s' has several annotations. Do you want to delete the content and the project anyway ?")% {'project_title':unicode(projects[0].title), 'title':unicode(content.title)}
    return errors, titles, message


@login_required
@transaction.commit_manually
def delete_content(request, iri_id=None):
    #Delete the project, the media if exists, and the content
    errors_transaction=[]  
    if not iri_id:
        iri_id = request.REQUEST.get("iri_id", None)  
    if iri_id:
        content = Content.safe_objects.get(iri_id=iri_id)
        try:
            if content.media_obj is not None:
                contents_media = Content.safe_objects.filter(media_obj = content.media_obj)
                #check if the media is ref by severals content
                if len(contents_media) < 2:
                    Media.safe_objects.get(id=content.media_obj.id).delete()
            project = content.front_project
            content.delete()
            if project is not None:
                Project.safe_objects.get(ldt_id= project.ldt_id).delete()
        except Exception, e:
            content.rollback()
            transaction.rollback()
            errors_transaction.append(_("Content deletion failure"))
            errors_transaction.append(e)
            return False, errors_transaction
        else:
            try:
                transaction.commit()
                content.commit()
                return True, errors_transaction
            except:
                content.rollback()
                transaction.rollback()
                errors_transaction.append(_("Commit of the content deletion failed"))
                errors_transaction.append(e)
                return False, errors_transaction

def upload(request):
    if request.method == 'POST':
        for field_name in request.FILES:
            # We get the file name
            source_file = request.FILES[field_name]
            source_filename = source_file.name
            # We sanitize the file name : no space, only lower case.
            source_filename = ldt_utils_path.sanitize_filename(source_filename)
            # We create the session temp folder if necessary
            if not os.path.exists(os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME])):
                os.makedirs(os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME]))
            destination_filepath = os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", source_filename)
            # We delete the existing file if necessary
            if os.path.exists(destination_filepath):
                os.remove(destination_filepath)
            
            destination_file = open(destination_filepath, "wb")
            
            for chunk in source_file.chunks():
                destination_file.write(chunk)
            destination_file.close()
            
        # indicate that everything is OK for SWFUpload
        return HttpResponse("ok", mimetype="text/plain")
    else:
        return HttpResponse("notok", mimetype="text/plain")

def remove_temp_file(request):
    # The filename arrives with a GET var.
    file_path = os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", ldt_utils_path.sanitize_filename(request.GET["filename"]))
    if os.path.exists(file_path):
        os.remove(file_path)
    return HttpResponse("remove ok", mimetype="text/plain")

def get_duration(request):
    try:
        # The filename arrives with a GET var.
        file_path = os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", ldt_utils_path.sanitize_filename(request.GET["filename"]))
        if hasattr(settings, 'FFMPEG_PATH') and os.path.exists(file_path):
            output = str(subprocess.Popen([settings.FFMPEG_PATH, "-i", file_path], stderr=subprocess.PIPE).communicate()[1])
            m = re.search("Duration:\s*?([\d.:]+)", output, re.M)
            dur_arr = m.group(1).split(":")
            td = datetime.timedelta(hours=int(dur_arr[0]), minutes=int(dur_arr[1]), seconds=float(dur_arr[2]))
            str_duration = str((td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6) / 10 ** 3)
            return HttpResponse(str_duration, mimetype="text/plain")
        else:
            return HttpResponse("", mimetype="text/plain")
    except Exception as inst:
        return HttpResponse(str(inst), mimetype="text/plain")

    
@login_required
def contents_filter(request, filter_c): 
    if filter_c and len(filter_c) > 0 and filter_c[0] == '_':
        filter_c = filter_c[1:]
    
    num_page = 0
    if request.GET.has_key('num_page'):
        num_page = int(request.GET["num_page"])
    tag_filter = ""
    if request.GET.has_key('tag_filter'):
        tag_filter = request.GET["tag_filter"]
    
    # We paginate the content list, in case of filter_c or not
    if filter_c and not tag_filter :
        content_nb = Content.safe_objects.filter(title__icontains=filter_c).count()
        nb_ct_pages = int(math.ceil(content_nb / settings.LDT_MAX_CONTENTS_PER_PAGE)) + 1
        content_list = Content.safe_objects.filter(title__icontains=filter_c)[(num_page*settings.LDT_MAX_CONTENTS_PER_PAGE):((num_page+1)*settings.LDT_MAX_CONTENTS_PER_PAGE)] #@UndefinedVariable
    elif filter_c and tag_filter :
        #TaggedItem.objects.get_by_model(Content.objects.all(), '"'+tag_filter+'"')
        content_nb = TaggedItem.objects.get_by_model(Content.safe_objects.filter(title__icontains=filter_c), '"'+tag_filter+'"').count()
        nb_ct_pages = int(math.ceil(content_nb / settings.LDT_MAX_CONTENTS_PER_PAGE)) + 1
        content_list = TaggedItem.objects.get_by_model(Content.safe_objects.filter(title__icontains=filter_c), '"'+tag_filter+'"')[(num_page*settings.LDT_MAX_CONTENTS_PER_PAGE):((num_page+1)*settings.LDT_MAX_CONTENTS_PER_PAGE)] #@UndefinedVariable
    elif tag_filter and not filter_c:
        content_nb = TaggedItem.objects.get_by_model(Content.safe_objects.all(), '"'+tag_filter+'"').count()
        nb_ct_pages = int(math.ceil(content_nb / settings.LDT_MAX_CONTENTS_PER_PAGE)) +1
        content_list = TaggedItem.objects.get_by_model(Content.safe_objects.all(), '"'+tag_filter+'"')[(num_page*settings.LDT_MAX_CONTENTS_PER_PAGE):((num_page+1)*settings.LDT_MAX_CONTENTS_PER_PAGE)] #@UndefinedVariable
    else:
        content_nb, nb_ct_pages, content_list = get_contents_page(num_page, request.user)
    #Change attributes with object permissions
    content_list = add_change_attr(request.user, content_list)
    # Get the all tags list
    tag_cloud = get_content_tags()
    
    is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
    return render_to_response("ldt/ldt_utils/partial/contentslist.html",
                              {'contents': content_list, 'nb_ct_pages': nb_ct_pages, 'content_nb': content_nb, 'current_content_page':float(num_page),
                               'tag_cloud': tag_cloud, 'current_content_tag':tag_filter, 'is_gecko': is_gecko
                               },
                              context_instance=RequestContext(request))
    

def get_contents_page(num_page, user):
    content_nb = float(Content.safe_objects.count()) #@UndefinedVariable
    nb_ct_pages = int(math.ceil(content_nb / settings.LDT_MAX_CONTENTS_PER_PAGE))
    content_list = add_change_attr(user, Content.safe_objects.all()[(num_page*settings.LDT_MAX_CONTENTS_PER_PAGE):((num_page+1)*settings.LDT_MAX_CONTENTS_PER_PAGE)]) #@UndefinedVariable
    return content_nb, nb_ct_pages, content_list


def get_content_tags(limit=None, steps=10):
    if limit is None:
        return Tag.objects.cloud_for_model(Content, steps=steps)
    else :
        return Tag.objects.cloud_for_model(Content, steps=steps)[:limit]
        
