import json
import lxml.etree
import math

from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import Group
from django.core.urlresolvers import reverse
from django.db.models import Q
from django.http import (HttpResponse, HttpResponseRedirect,
    HttpResponseServerError)
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.utils.translation import ugettext as _
from guardian.shortcuts import get_objects_for_group, get_objects_for_user

from ldt.ldt_utils.forms import LdtAddForm, AddProjectForm, CopyProjectForm
from ldt.ldt_utils.models import Content, Project
from ldt.ldt_utils.utils import boolean_convert
from ldt.security.utils import (assign_perm_to_obj, add_change_attr, get_userlist,
    get_userlist_model)
from ldt.user.forms import PictureForm


@login_required
def create_ldt_view(request):
    redirect_to = ''
    if request.method == "POST" :
        form = LdtAddForm(request.POST)
        picture_form = PictureForm(None, request.POST, request.FILES)
        form_status = "none"
        contents = Content.safe_objects.all()
        
        if form.is_valid() and picture_form.is_valid():              
                     
            user = request.user                      
            project = Project.create_project(title=form.cleaned_data['title'], user=user, 
                                             contents=form.cleaned_data['contents'],
                                             description=form.cleaned_data['description'],
                                             set_icon=False)
            
            picture_form.model = project
            picture_form.save()
            
            if form.cleaned_data["share"]:
                assign_perm_to_obj(project, form.cleaned_data["read_list"], form.cleaned_data["write_list"], user)
            form_status = "saved"
            is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
            if is_gecko :
                redirect_to = reverse('index_project_full', kwargs={'id':project.ldt_id})
            else:
                return HttpResponseRedirect(reverse('index_project', kwargs={'id':project.ldt_id}))   
     
    else:
        form = LdtAddForm()
        picture_form = PictureForm()
        contents = Content.safe_objects.all()             
        form_status = "none"    
    
    return render_to_response('ldt/ldt_utils/create_ldt.html', {'contents': contents, 'form': form, 'form_status':form_status,
                                                                'redirect_to': redirect_to, 'create_project_action':reverse(create_ldt_view), 'language_code' : settings.LANGUAGE_CODE[2:],
                                                                'elem_list': get_userlist(request.user), 'profile_picture_form': picture_form}, context_instance=RequestContext(request))
   
  

@login_required
def create_project(request, iri_id): 
    content = get_object_or_404(Content.safe_objects, iri_id=iri_id)
    contents = [ content, ]
    groups = request.user.groups.exclude(name=settings.PUBLIC_GROUP_NAME)
    redirect_to = ''
    form_status = "none"
    
    if request.method == "POST" :        
        form = AddProjectForm(request.POST)
        picture_form = PictureForm(None, request.POST, request.FILES)
        
        if form.is_valid() and picture_form.is_valid():
            user = request.user
            project = Project.create_project(title=form.cleaned_data['title'],
                                             user=user, contents=contents, 
                                             description=form.cleaned_data['description'], 
                                             set_icon=False)
            picture_form.model = project
            picture_form.save()
                                   
            form_status = "saved"
            if form.cleaned_data["share"]:
                assign_perm_to_obj(project, form.cleaned_data["read_list"], form.cleaned_data["write_list"], user)

            # Modal window is not used with firefox
            is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
            if is_gecko :
                redirect_to = reverse('index_project_full', kwargs={'id':project.ldt_id})
            else:
                return HttpResponseRedirect(reverse('index_project', kwargs={'id':project.ldt_id}))
    else:
        form = AddProjectForm()
           
    return render_to_response('ldt/ldt_utils/create_ldt.html', {'form':form, 'form_status': form_status, 'contents':contents,'groups' : groups,
                                                                'redirect_to': redirect_to, 'elem_list': get_userlist(request.user), 'create_project_action':reverse("ldt.ldt_utils.views.project.create_project", kwargs={'iri_id':iri_id})}, context_instance=RequestContext(request))

@login_required
def update_project(request, ldt_id):
    project = get_object_or_404(Project.safe_objects, ldt_id=ldt_id)
    contents = project.contents.all()
    groups = request.user.groups.exclude(name=settings.PUBLIC_GROUP_NAME)
    member_list, admin_list = get_userlist_model(project, request.user)
    display_reset= False
    
    if contents and len(contents)>0:
        if contents[0].front_project != None:
            if contents[0].front_project.ldt_id == ldt_id:
                display_reset = True        
    
    if request.method == "POST" :
        submit_action = request.REQUEST.get("submit_button", False)
        if submit_action == "prepare_delete":
            errors = []
            if project.state == 2:
                errors.append(_("the project %(title)s is published. please unpublish before deleting.") % {'title':project.title})
                message = _("can not delete the project. Please correct the following error")
                title = _('title error deleting project')
            elif project.content_set.count() != 0:
                errors.append(_("the project %(title)s is the front project of %(content)s. please delete this content first.") % {'title':project.title, 'content':project.content_set.all()[0]})
                message = _("can not delete the project. Please correct the following error")
                title = _('title error deleting project')
            else:
                message = _("please confirm deleting project %(title)s") % {'title':project.title}
                title = _("confirm deletion")
            return render_to_response('ldt/ldt_utils/error_confirm_popup.html', {'errors':errors, 'message':message, 'title': title}, context_instance=RequestContext(request))
        elif submit_action == "delete":
            if project.state != 2:
                project.delete()
            form_status = 'deleted'
            form = AddProjectForm()
            picture_form = PictureForm()
        elif submit_action == "prepare_reset":
            errors=[]
            message = _("please confirm reseting project %(title)s") % {'title':project.title}
            title = _("confirm reset")
            return render_to_response('ldt/ldt_utils/reset_confirm_popup.html', {'errors':errors, 'message':message, 'title': title}, context_instance=RequestContext(request))
        elif submit_action == "reset":
            #TODO : verifier index de la recher maj
            contents[0].create_front_project()
            contents[0].save()
            project.delete()
            form_status= 'saved'
            form = AddProjectForm()
            picture_form = PictureForm()
        else:
            form_status = 'none' 
            form = AddProjectForm(request.POST)
            picture_form = PictureForm(None, request.POST, request.FILES)
            
            if form.is_valid() and picture_form.is_valid():          
                if project.title != form.cleaned_data['title'] or project.description != form.cleaned_data['description']:
                    project.title = form.cleaned_data['title']
                    project.description = form.cleaned_data['description']
                    ldt = lxml.etree.fromstring(project.ldt_encoded)
                    res = ldt.xpath("/iri/project")
                    res[0].set("title", project.title)
                    res[0].set("abstract", project.description)
                    project.ldt = lxml.etree.tostring(ldt, pretty_print=True)
                    project.save()                    
                 
                picture_form.model = project
                picture_form.save()   
                assign_perm_to_obj(project, form.cleaned_data["read_list"], form.cleaned_data["write_list"], request.user)
                form_status = "saved"
    else:
        form = AddProjectForm({'title':unicode(project.title), 'description':unicode(project.get_description())})
        picture_form = PictureForm()
        
        form_status = 'none'
        
    return render_to_response('ldt/ldt_utils/create_ldt.html', {'form':form, 'form_status':form_status, 'groups': groups, 'elem_list': get_userlist(request.user), 
                                                                'ldt_id': ldt_id, 'contents':contents, 'display_reset':display_reset, 'member_list': member_list, 'admin_list': admin_list,
                                                                'create_project_action':reverse("ldt.ldt_utils.views.project.update_project", kwargs={'ldt_id':ldt_id}),
                                                                'profile_picture_form': picture_form}, context_instance=RequestContext(request))

@login_required
def copy_project(request, ldt_id, group_id=0): 
    
    project = get_object_or_404(Project.safe_objects, ldt_id=ldt_id)
    if request.method == "POST" :
        form = CopyProjectForm(request.POST)
        
        if form.is_valid():
            user = request.user
            group_id = form.cleaned_data['group']
            group = Group.objects.get(id=group_id) if group_id and group_id > 0 else None
            project = project.copy_project(title=form.cleaned_data['title'], user=user, group=group)
            is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
            if is_gecko:
                return HttpResponseRedirect(reverse('index_project_full', kwargs={'id':project.ldt_id}))
            else:
                return HttpResponseRedirect(reverse('index_project', kwargs={'id':project.ldt_id}))
    else:
        form = CopyProjectForm()
    # Modal window is not used with firefox, so we ask to submit the form in _parent in firefox case.
    target_parent = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
    return render_to_response('ldt/ldt_utils/copy_ldt.html', {'form':form, 'project':project, 'group_id':group_id, 'target_parent':target_parent}, context_instance=RequestContext(request))


@login_required
def projects_filter(request, filter, is_owner=False, status=0, id_group=0):  # @ReservedAssignment
    is_owner = boolean_convert(is_owner)
    status = int(status)
    id_group = int(id_group)
    query = Q()

    if is_owner:
        owner = None
        try:
            owner = request.user
        except:
            return HttpResponseServerError("<h1>User not found</h1>")
        query &= Q(owner=owner)

    if status > 0:
        query &= Q(state=status)

    if filter:
        if len(filter) > 0 and filter[0] == '_':
            filter = filter[1:]  # @ReservedAssignment
        query &= Q(title__icontains=filter)
           
    is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
    show_username = True
    
    project_nb = None
    nb_pj_pages = None
    num_page = 0
    if request.GET.has_key('num_page'):
        num_page = int(request.GET["num_page"])
    
    if id_group > 0:    # Search inside a group
        grp = Group.objects.get(id=id_group)
        project_list = get_objects_for_group(grp, 'ldt_utils.view_project').filter(query)
        project_list = add_change_attr(request.user, project_list)
    elif id_group == -1:# Search inside projects shared with a specific user
        project_list = get_objects_for_user(request.user, 'ldt_utils.view_project', use_groups=False).exclude(owner=request.user)
        project_list = add_change_attr(request.user, project_list)
    else:
        # We paginate in these cases : user's project or published
        if status==2:
            project_list = Project.safe_objects.filter(query).select_related("owner").exclude(title__startswith='front')
        else:
            project_list = Project.safe_objects.filter(query).select_related("owner")
        project_nb = float(project_list.count()) #@UndefinedVariable
        nb_pj_pages = int(math.ceil(project_nb / settings.LDT_MAX_PROJECTS_PER_PAGE))
        project_list = project_list[(num_page*settings.LDT_MAX_PROJECTS_PER_PAGE):((num_page+1)*settings.LDT_MAX_PROJECTS_PER_PAGE)] #@UndefinedVariable
        show_username = False

    if status == 2:
        url_templ = "ldt/ldt_utils/partial/publishedprojectslist.html"
    else:
        url_templ = "ldt/ldt_utils/partial/projectslist.html"
    
    return render_to_response(url_templ,
                              {'projects': project_list, 'nb_pj_pages': nb_pj_pages, 'project_nb': project_nb, 'current_project_page':float(num_page),
                               'show_username':show_username, 'group_id':id_group, 'is_gecko': is_gecko
                               },
                              context_instance=RequestContext(request))
       
@login_required
def publish(request, id):  # @ReservedAssignment
    ldt = get_object_or_404(Project.safe_objects, ldt_id=id)
    ldt.publish()
    return HttpResponse(json.dumps({'res':True, 'ldt': {'id': ldt.id, 'state':ldt.state, 'ldt_id': ldt.ldt_id}}, ensure_ascii=False), content_type='application/json')

@login_required
def unpublish(request, id):  # @ReservedAssignment
    ldt = get_object_or_404(Project.safe_objects, ldt_id=id)
    ldt.unpublish()
    return HttpResponse(json.dumps({'res':True, 'ldt': {'id': ldt.id, 'state':ldt.state, 'ldt_id': ldt.ldt_id}}, ensure_ascii=False), content_type='application/json')

  
def created_ldt(request):
    return render_to_response('ldt/ldt_utils/save_done.html', context_instance=RequestContext(request))


def get_projects_page(num_page, user):
    project_nb = float(Project.safe_objects.filter(owner=user).count()) #@UndefinedVariable
    nb_pj_pages = int(math.ceil(project_nb / settings.LDT_MAX_PROJECTS_PER_PAGE))
    # add_change_attr is not useful because user and project's owner are the same
    project_list = Project.safe_objects.filter(owner=user).select_related("owner")[(num_page*settings.LDT_MAX_PROJECTS_PER_PAGE):((num_page+1)*settings.LDT_MAX_PROJECTS_PER_PAGE)] #@UndefinedVariable
    return project_nb, nb_pj_pages, project_list


def get_published_projects_page(num_page):
    project_nb = float(Project.safe_objects.filter(state=2).exclude(title__startswith='front').count()) #@UndefinedVariable
    nb_pj_pages = int(math.ceil(project_nb / settings.LDT_MAX_PROJECTS_PER_PAGE))
    project_list = Project.safe_objects.filter(state=2).exclude(title__startswith='front')[(num_page*settings.LDT_MAX_PROJECTS_PER_PAGE):((num_page+1)*settings.LDT_MAX_PROJECTS_PER_PAGE)] #@UndefinedVariable
    return project_nb, nb_pj_pages, project_list
