# -*- coding: utf-8 -*-
'''
Created on Aug 08, 2013

@author: rvelt
'''

from core.models import (Notice, Thesaurus, Term)
from jocondelab.models import (DbpediaFields, Country, ContributableTerm, TagcloudTerm)
from django.core.paginator import Paginator
import django.utils.simplejson as json
from django.conf import settings
from django.views.generic import DetailView, TemplateView
from django.db.models import Sum, Count
import random

class SearchView(TemplateView):
    
    # This view is used for
    # - the home and search pages, displaying random images
    # - search result pages
    # - ajax-fetched results
    
    def get(self, request):
                
        context = {}
        lang = request.GET.get('lang',request.LANGUAGE_CODE)[:2]
        page = request.GET.get('page',1)
        querystr = request.GET.get('q', "")
        is_ajax = request.is_ajax()
        queryterms = [s.strip(" ") for s in querystr.split(";") if s.strip(" ")]
        dbpedia_uri = request.GET.get('dbpedia_uri', None)
        from_year = request.GET.get('from_year', None)
        to_year = request.GET.get('to_year', from_year)
        show_years = request.GET.get('show_years',False)
        emptysearch = ((not queryterms) and (not dbpedia_uri) and (not from_year))
        npp = request.GET.get('count', 12 if emptysearch else 30)
        context["lang"] = lang
        context["current_page"] = page
        
        if self.template_name is None:
            if is_ajax and page > 1:
                self.template_name = "jocondelab/partial/notice_list.html"
            else:
                if is_ajax:
                    self.template_name = "jocondelab/partial/wrapped_notice_list.html"
                else:
                    self.template_name = "jocondelab/front_search.html"
        
        qs = Notice.objects.filter(image=True)
        
        if emptysearch:
            context["count"] = qs.count()
            ns = qs.order_by('?')[:npp]
        else:
            if dbpedia_uri:
                qs = qs.filter(noticeterm__term__dbpedia_uri=dbpedia_uri)
                context["queryobj"] = json.dumps({'dbpedia_uri': dbpedia_uri})
                if page == 1:
                    termobj = Term.objects.filter(dbpedia_uri=dbpedia_uri)[0]
                    if termobj:
                        termtrans = termobj.dbpedia_fields.filter(language_code = lang)
                        if termtrans.exists():
                            context["wkinfo"] = termtrans[0]
                            context["searchterm"] = termtrans[0].label
                        else:
                            context["searchterm"] = termobj.label
            if queryterms:
                context["searchterm"] = querystr
                context["queryobj"] = json.dumps({'q': querystr})
                for i, term in enumerate(queryterms):
                    fs = DbpediaFields.objects.filter(label=term, language_code=lang)
                    if i == 0 and page == 1 and len(queryterms) == 1 and fs.exists():
                        context["wkinfo"] = fs[0]
                    fs = fs.values('term_id').distinct()
                    qs = qs.filter(noticeterm__term__in=fs)
            if from_year:
                context["queryobj"] = json.dumps({'from_year': from_year, 'to_year': to_year})
                context["searchterm"] = u"%s – %s"%(from_year, to_year)
                qs = qs.filter(years__start_year__lte=to_year, years__end_year__gte=from_year)
            qs = qs.order_by('id').distinct()
            paginator = Paginator(qs, npp)
            context["count"] = paginator.count
            ns = paginator.page(page)
            context["page_count"] = paginator.num_pages
        
        notices = []
        thesauruscache = {th.id: th.label for th in Thesaurus.objects.all()}
        for n in ns:
            terms = [{
                "locale_label": t.dbpedia_fields.get(language_code=lang).label,
                "thesaurus": thesauruscache[t.thesaurus_id],
                "dbpedia_uri": t.dbpedia_uri
            } for t in Term.objects.filter(noticeterm__notice=n,dbpedia_fields__language_code=lang).distinct()]
            termsbythesaurus = {}
            for term in terms:
                if not term["thesaurus"] in termsbythesaurus:
                    termsbythesaurus[term["thesaurus"]] = []
                termsbythesaurus[term["thesaurus"]].append(term)
            noticedict = {
                "id": n.id,
                "imagetitle": n.titr if n.titr else n.deno,
                "title": n.titr,
                "denomination": n.deno,
                "image": (settings.JOCONDE_IMG_BASE_URL + n.images.all()[0].url) if n.images.exists() else "",
                "author": n.autr,
                "terms_by_thesaurus": termsbythesaurus,
            }
            if show_years and n.years.exists():
                noticedict["years"] = [n.years.all()[0].start_year, n.years.all()[0].end_year]
            notices.append(noticedict)
        context["notices"] = notices
                        
        return self.render_to_response(context)

class GeoView(TemplateView):
    
    template_name = "jocondelab/front_geo.html"
    
    def get(self, request):
        
        context = {}
        cqs = Country.objects.order_by('-nb_notices')
        context["countries"] = json.dumps([c for c in cqs.values('dbpedia_uri','iso_code_3','nb_notices')])
        
        return self.render_to_response(context)
    
class NoticeView(DetailView):
    
    model = Notice
    template_name = "jocondelab/front_notice.html"
    show_contributions = True
    
    def get_context_data(self, **kwargs):
        
        context = super(NoticeView, self).get_context_data(**kwargs)
        lang = self.request.GET.get('lang',self.request.LANGUAGE_CODE)[:2]
        
        context["images"] = [settings.JOCONDE_IMG_BASE_URL + i.url for i in self.object.images.exclude(relative_url__endswith='v.jpg')]
        context["title"] = self.object.titr if self.object.titr else self.object.deno
        
        termsbythesaurus = {}
        for nt in Term.objects.filter(noticeterm__notice=self.object, dbpedia_fields=None).select_related('thesaurus').order_by('label').distinct():
            term = {
                "thesaurus": nt.thesaurus.label,
                "dbpedia_uri": nt.dbpedia_uri,
                "translated": False,
                "label": nt.label
            }
            if not term["thesaurus"] in termsbythesaurus:
                termsbythesaurus[term["thesaurus"]] = {
                   "translated": [],
                   "untranslated": []
                   }
            termsbythesaurus[term["thesaurus"]]["untranslated"].append(term)
        for nt in Term.objects.filter(noticeterm__notice=self.object, dbpedia_fields__language_code=lang).select_related('thesaurus,dbpedia_fields').order_by('dbpedia_fields__label').distinct():
            term = {
                "thesaurus": nt.thesaurus.label,
                "dbpedia_uri": nt.dbpedia_uri,
                "translated": True,
                "label": nt.dbpedia_fields.get(language_code = lang).label
            }
            if not term["thesaurus"] in termsbythesaurus:
                termsbythesaurus[term["thesaurus"]] = {
                   "translated": [],
                   "untranslated": []
                   }
            termsbythesaurus[term["thesaurus"]]["translated"].append(term)
        context["terms_by_thesaurus"] = termsbythesaurus
        
        if self.show_contributions:
            cqs = self.object.contribution_set.select_related('term__dbpedia_fields')
            contributions = [{
                    "label": ct.term.dbpedia_fields.get(language_code=lang).label,
                    "dbpedia_uri": ct.term.dbpedia_uri,
                    "contribution_id": ct.id,
                    "li_style": "positive" if ct.contribution_count > 0 else "null",
                    "font_size": "%.1f"%(12. + .5 * max(0., min(12., ct.contribution_count))),
                    "vote_mode": True
                } for ct in cqs.filter(thesaurus=None,term__dbpedia_fields__language_code=lang).order_by('-contribution_count')]
            context["contributions"] = contributions
        
        context['wikipedia_urls'] = json.dumps(settings.WIKIPEDIA_URLS)
        context['JOCONDE_NOTICE_BASE_URL'] = settings.JOCONDE_NOTICE_BASE_URL
        
        return context
    
    def get_object(self):
        if self.pk_url_kwarg in self.kwargs:
            return super(NoticeView, self).get_object()
        else:
            queryset = self.get_queryset().filter(image=True, repr='', peri__contains='4e quart 19e siècle', noticeterm__term__id__in=ContributableTerm.objects.values('term__id'))
            return queryset[random.randint(0, queryset.count() - 1)]

class FrontTermListView(TemplateView):
    
    template_name = "jocondelab/front_termlist.html"
    
    def get(self, request):
        
        context = {}
        lang = self.request.GET.get('lang',self.request.LANGUAGE_CODE)[:2]
        is_ajax = request.is_ajax()
        letter = self.request.GET.get('letter',None)
        alpha_sort = (letter is not None) or self.request.GET.get('alphabet',False)
        context['alpha_sort'] = alpha_sort
        thesaurus = self.request.GET.get('thesaurus',None)
        context['thesaurus'] = thesaurus
        
        if is_ajax:
            self.template_name = "jocondelab/partial/termlist_contents.html"
        
        if thesaurus is None:
            wqs = TagcloudTerm.objects.filter(term__dbpedia_fields__language_code=lang).values('term__dbpedia_fields__label','term__dbpedia_uri')
            wqs = wqs.distinct().annotate(sum_notice=Sum('term__nb_notice')).order_by('-sum_notice')
            n = wqs.count()
            context['words'] = [{
                     'label': w['term__dbpedia_fields__label'],
                     'uri': w['term__dbpedia_uri'],
                     'font_size': "%.2f"%(1. + float(n-i)/n)
                                 } for i, w in enumerate(wqs)]
            random.shuffle(context['words'])
        else:
            alphabets = [{
                  "languages": [ "fr", "en", "de", "it", "es", "pt", "ca", "br", "eu", "oc" ],
                  "letters": u"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
              }, {
                  "languages": [ "ru" ],
                  "letters": u"АБВГДЕЖЗИКЛМНОПРСТУФХЦЧШЩЭЮЯ"
              }, {
                  "languages": [ "ar" ],
                  "letters": u"ابتثجحخدذرزسشصضطظعغفقكلمنهوي"
            }]
            latinalph = alphabets[0]
            alphabet = None
            for a in alphabets:
                if lang in a["languages"]:
                    alphabet = a
            if alphabet is not None:
                if thesaurus in ['REPR','AUTR']:
                    context["show_alphabet"] = True
                letters = alphabet["letters"]
                context["alphabet"] = letters
                if letter is not None:
                    letterpos = letters.find(letter)
            context["current_letter"] = letter
            if (not alpha_sort) or (thesaurus == 'AUTR' and alphabet == latinalph and letter is not None):
                tqs = Term.objects.filter(dbpedia_fields__language_code=lang)
                if thesaurus == 'REPR':
                    tqs = tqs.filter(thesaurus__label__in=['REPR','SREP'])
                else:
                    tqs = tqs.filter(thesaurus__label=thesaurus)
                if alpha_sort:
                    # Particular case in which thesaurus == AUTR and the alphabet is latin,
                    # we use original sorting by family name
                    if letterpos >= 0:
                        tqs = tqs.filter(label__gte=letters[letterpos])
                    if letterpos < len(letters)-1:
                        tqs = tqs.filter(label__lt=letters[letterpos+1])
                    tqs = tqs.filter(notices__image=True).distinct('label').order_by('label').select_related('notices__images')
                    tqs = tqs.values('notices__images__relative_url','dbpedia_uri','dbpedia_fields__abstract','label')
                    terms = []
                    known_uris = []
                    for t in tqs:
                        uri = t['dbpedia_uri']
                        if uri not in known_uris:
                            terms.append(t)
                            known_uris.append(uri)
                else:
                    # When we're in sort by most frequent terms
                    tqs = tqs.order_by('-nb_notice').extra(select={
                              'image_url': 'SELECT relative_url FROM core_noticeimage AS JL01 JOIN core_notice AS JL02 ON JL02.id = JL01.notice_id JOIN core_noticeterm AS JL03 ON JL02.id = JL03.notice_id WHERE JL03.term_id = core_term.id LIMIT 1'
                          })[:80]
                    tqs = tqs.values('image_url','dbpedia_fields__thumbnail','dbpedia_uri','dbpedia_fields__abstract','dbpedia_fields__label')
                    terms = [t for t in tqs if t['image_url']][:60]
                terms = [{
                      "dbpedia_uri": t['dbpedia_uri'],
                      "label": t.get('dbpedia_fields__label',t.get('label','')),
                      "abstract": t['dbpedia_fields__abstract'],
                      "image_url": "%s%s"%(settings.JOCONDE_IMG_BASE_URL, t.get('image_url',t.get('notices__images__relative_url','')))
                            } for t in terms]
                context['termcount'] = len(terms)
            else:
                tqs = DbpediaFields.objects.filter(language_code=lang,term__notices__image=True).exclude(label=None)
                if thesaurus == 'REPR':
                    tqs = tqs.filter(term__thesaurus__label__in=['REPR','SREP'])
                else:
                    tqs = tqs.filter(term__thesaurus__label=thesaurus)
                if thesaurus in ['REPR','AUTR'] and letter is not None: #Pagination required for these two thesaura
                    if alphabet is not None:
                        if letterpos >= 0:
                            tqs = tqs.filter(label__gte=letters[letterpos])
                        if letterpos < len(letters)-1:
                            tqs = tqs.filter(label__lt=letters[letterpos+1])
                tqs = tqs.distinct('label').order_by('label')
                terms = tqs.select_related('term__notices__images').values('term__notices__images__relative_url','dbpedia_uri','abstract','label')
                for t in terms:
                    t['image_url'] = "%s%s"%(settings.JOCONDE_IMG_BASE_URL, t['term__notices__images__relative_url'])
                context['termcount'] = terms.count()
            context['terms'] = terms
        
        return self.render_to_response(context)
    