from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.core.urlresolvers import reverse
from django.db.models.aggregates import Max
from django.http.response import HttpResponseForbidden
from django.shortcuts import get_object_or_404, render_to_response, redirect
from django.template import RequestContext
from django.utils.translation import ugettext as _
from egonomy.models import ImageMetadata, Image, Fragment
from egonomy.search_indexes import QueryParser
from egonomy.search_indexes.paginator import SearchPaginator
from egonomy.search_indexes.query import ModelRelatedSearchQuerySet
from haystack.query import RelatedSearchQuerySet
import logging

logger = logging.getLogger(__name__)


def home(request):
    
    # We force list() because if not, img_id_list is a valuelistqueryset and not a list of values.
    # We separate image requests and make requests with select_related to optimize database hits.
    img_id_list = list(Image.objects.values_list('id', flat=True).annotate(date_modif=Max('fragment__date_saved')).exclude(date_modif=None).order_by('-date_modif')[:12])
    img_list = Image.objects.filter(id__in=img_id_list).select_related('info', 'metadata')
    frg_list = Fragment.objects.all().order_by('-date_saved').select_related('image', 'image__info', 'image__metadata','author')[:12]
    
    return render_to_response("egonomy_home.html",
                              {'img_list':img_list, 'fragment_list':frg_list},
                              context_instance=RequestContext(request))


def annotate_picture(request, image_id):

    img = get_object_or_404(Image.objects.select_related('info', 'metadata'), id=image_id)
    
    # We force list() to get only one database hit instead of 3 (first request, count, [0])
    frg_list = list(Fragment.objects.filter(image=img).order_by('-date_saved').select_related('image', 'image__info', 'image__metadata','author'))
    last_frg = None
    if len(frg_list)>0:
        last_frg = frg_list[0]
    
    return render_to_response("egonomy_annotate_picture.html",
                              {'img': img, 'fragment_list': frg_list, 'last_frg':last_frg},
                              context_instance=RequestContext(request))


def view_fragment(request, fragment_pk):
    
    frg = get_object_or_404(Fragment.objects.select_related('image', 'image__info', 'image__metadata','author'), pk=fragment_pk)
    frg_list = Fragment.objects.filter(image=frg.image).select_related('image', 'image__info', 'image__metadata','author')
    
    fragment_only = {'true': True, 'false': False, "0": False, "1": True}.get((request.GET.get("fragment_only") or "1").lower())
    
    return render_to_response("egonomy_view_fragment.html",
                              {'fragment': frg, 'fragment_list': frg_list, 'fragment_only':fragment_only},
                              context_instance=RequestContext(request))

@login_required
def create_fragment(request, image_id, fragment_pk=None):
    
    img = get_object_or_404(Image.objects.select_related('info', 'metadata'), id=image_id)
    frg_list = Fragment.objects.filter(image=img).order_by('-date_saved').select_related('image', 'image__info', 'image__metadata','author')
    frg_to_modify = False
    frg_data = None
    if fragment_pk:
        frg_data = get_object_or_404(Fragment.objects.select_related('author'), pk=fragment_pk)
        # We check if the current user is the fragment's author
        if frg_data.author != request.user:
            return HttpResponseForbidden(_("You are not allowed to modify this fragment."))
        frg_to_modify = True
    else:
        frg_duplicate_pk = request.GET.get("duplicate") or None
        if frg_duplicate_pk:
            frg_data = get_object_or_404(Fragment.objects.select_related('author'), pk=frg_duplicate_pk)
    
    return render_to_response("egonomy_create_fragment.html",
                              {'img': img, 'frg_data': frg_data,  'frg_to_modify': frg_to_modify, 'fragment_list': frg_list},
                              context_instance=RequestContext(request))

@login_required
def save_fragment(request):
    
    frg_title = request.POST["fragment_title"]
    frg_desc = request.POST["fragment_description"]
    frg_kw = request.POST["user_keywords"]
    frg_path = request.POST["fragment_path"]
    frg_image_id = request.POST["image_id"]
    if "fragment_pk" in request.POST:
        frg_pk = request.POST["fragment_pk"]
        frg = get_object_or_404(Fragment.objects.select_related('author'), pk=frg_pk)
        # We check if the current user is the fragment's author
        if frg.author != request.user:
            return HttpResponseForbidden(_("You are not allowed to modify this fragment."))
    else :
        img = get_object_or_404(Image, id=frg_image_id)
        frg = Fragment()
        frg.image = img
        frg.author = request.user
    
    frg.coordinates = frg_path
    frg.title = frg_title
    frg.description = frg_desc
    frg.tags = frg_kw
    frg.save()
    
    return redirect("view_fragment", fragment_pk=frg.pk)


def all_pictures(request):
    
    # Get the cur_page_nb number parameter if possible
    cur_page_nb = request.GET.get("page") or 1
    cur_page_nb = int(cur_page_nb)

    search = None
    nb_results = 1
    if "search" in request.GET:
        search = request.GET["search"]
        field = "all"
        if "field" in request.GET:
            field = request.GET["field"]

    img_list = Image.objects.select_related('info', 'metadata')
    nb = request.GET.get("limit") or getattr(settings,"IMAGES_PER_PAGE", 32)
    if search:
        if not field or field == 'all':
            field = 'text'
        qp = QueryParser(field)
        res = ModelRelatedSearchQuerySet(model=Image).filter(qp.parse(search)).models(ImageMetadata).load_all_queryset(Image, img_list).load_all()
        paginator = SearchPaginator(res, nb)
    else:
        img_list = img_list.order_by('pk').all()
        paginator = Paginator(img_list, nb)
    
    try:
        results = paginator.page(cur_page_nb)
    except (EmptyPage, InvalidPage):
        results = paginator.page(paginator.num_pages)
    
    url_pagination = reverse("all_pictures") + "?limit=" + str(nb)
    if search:
        url_pagination = url_pagination + "&search=" + search

    return render_to_response("egonomy_all_pictures.html",
                              {'results':results, 'nb_pages':paginator.num_pages, 'cur_page_nb':cur_page_nb, "search":search, "nb_results":nb_results, "url_pagination":url_pagination},
                              context_instance=RequestContext(request))


def all_fragments(request):
        
    # Get the cur_page_nb number parameter if possible
    cur_page_nb = request.GET.get("page") or 1
    cur_page_nb = int(cur_page_nb)

    search = None
    nb_results = 1
    if "search" in request.GET:
        search = request.GET["search"]
        field = "all"
        if "field" in request.GET:
            field = request.GET["field"]

    frg_list = Fragment.objects.select_related('image', 'image__info', 'image__metadata','author')
    nb = request.GET.get("limit") or getattr(settings,"IMAGES_PER_PAGE", 32)
    if search:
        if not field or field == 'all':
            field = 'text'
        qp = QueryParser(field)
        res = RelatedSearchQuerySet().filter(qp.parse(search)).models(Fragment).load_all_queryset(Fragment, frg_list).load_all().highlight()
        paginator = Paginator(res, nb)
    else:
        frg_list = frg_list.order_by('pk').all()
        paginator = Paginator(frg_list, nb)
        
    try:
        results = paginator.page(cur_page_nb)
    except (EmptyPage, InvalidPage):
        results = paginator.page(paginator.num_pages)
        
    url_pagination = reverse("all_fragments") + "?limit=" + str(nb)
    if search:
        url_pagination = url_pagination + "&search=" + search

    return render_to_response("egonomy_all_fragments.html",
                              {"search_fragment":True, 'results':results, 'nb_pages':paginator.num_pages, 'cur_page_nb':cur_page_nb, "search":search, "nb_results":nb_results, "url_pagination":url_pagination},
                              context_instance=RequestContext(request))


def user_fragments(request, username):
        
    # Get the cur_page_nb number parameter if possible
    cur_page_nb = request.GET.get("page") or 1
    cur_page_nb = int(cur_page_nb)
    # get the username
    user = get_object_or_404(User, username=username)
    
    frg_list = Fragment.objects.filter(author=user).order_by('-date_saved').select_related('image', 'image__info', 'image__metadata','author')
    nb = request.GET.get("limit") or getattr(settings,"IMAGES_PER_PAGE", 32)
    paginator = Paginator(frg_list, nb)
        
    try:
        results = paginator.page(cur_page_nb)
    except (EmptyPage, InvalidPage):
        results = paginator.page(paginator.num_pages)
        
    url_pagination = reverse("user_fragments", args=[username]) + "?limit=" + str(nb)

    return render_to_response("egonomy_all_fragments.html",
                              {"user_fragments":True, 'username':username, 'results':results, 'nb_pages':paginator.num_pages, "search":None, 'cur_page_nb':cur_page_nb, "url_pagination":url_pagination},
                              context_instance=RequestContext(request))



