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

@author: rvelt
'''

import json
import logging

from django.conf import settings
from django.db.models import Sum
from django.http import HttpResponse
from django.http.response import HttpResponseBadRequest
from django.views.generic import TemplateView
import requests

from core.models import Notice, Thesaurus
from jocondelab.models import (DbpediaYears, DbpediaGeo, DbpediaFields, 
    ContributedTerm, ContributedFields, Contribution)


logger = logging.getLogger(__name__)

def terms(request):
    
    lang = request.GET.get('lang', request.LANGUAGE_CODE)[:2]
    q = request.GET.get('term', None)
    count = request.GET.get('count', 20)
    qs = DbpediaFields.objects.filter(term__nb_illustrated_notice__gt=0,language_code=lang)
    if lang in [ "fr", "en", "de", "it", "es", "pt", "ca", "br", "eu", "oc" ]:
        qs = qs.filter(label__iregex=r"\y%s"%q)
    else:
        qs = qs.filter(label__icontains=q)
    qs = qs.values('dbpedia_uri','label').distinct().order_by('label')[:count]
    res = [{"dbpedia_uri": r['dbpedia_uri'], "label": r['label']} for r in qs]
    return HttpResponse(content=json.dumps(res), mimetype='application/json')

def years(request):
    
    lang = request.GET.get('lang', request.LANGUAGE_CODE)[:2]
    from_year = request.GET.get('from_year', None)
    to_year = request.GET.get('to_year', None)
    count = request.GET.get('count', 20)
    
    qs = DbpediaYears.objects.filter(term__nb_illustrated_notice__gt=0,term__dbpedia_fields__language_code=lang)
    if to_year:
        qs = qs.filter(start_year__lte=to_year)
    if from_year:
        qs = qs.filter(end_year__gte=from_year)
    qs = qs.values('start_year','end_year','term__dbpedia_fields__label','term__dbpedia_uri')
    qs = qs.annotate(sum_notices=Sum('term__nb_illustrated_notice')).order_by('-sum_notices')
    
    qs = qs[:count]
    
    results = [{
                "start_year": y["start_year"],
                "end_year": y["end_year"],
                "label": y["term__dbpedia_fields__label"],
                "sum_notices": y["sum_notices"],
                "dbpedia_uri": y["term__dbpedia_uri"]
                } for y in qs]
    
    return HttpResponse(content=json.dumps(results), mimetype='application/json')

def geo_coords(request):
    
    lang = request.GET.get('lang', request.LANGUAGE_CODE)[:2]
    min_lat = request.GET.get('min_lat', None)
    max_lat = request.GET.get('max_lat', None)
    min_lng = request.GET.get('min_lng', None)
    max_lng = request.GET.get('max_lng', None)
    count = request.GET.get('count', 20)
    
    qs = DbpediaGeo.objects.filter(term__dbpedia_fields__language_code=lang,term__nb_illustrated_notice__gt=0)
    
    if min_lat:
        qs = qs.filter(latitude__gt=min_lat)
    if max_lat:
        qs = qs.filter(latitude__lt=max_lat)
    if min_lng:
        qs = qs.filter(longitude__gt=min_lng)
    if max_lng:
        qs = qs.filter(longitude__lt=max_lng)
    
    qs = qs.values('latitude','longitude','term__dbpedia_fields__label','term__dbpedia_uri')
    qs = qs.annotate(sum_notices=Sum('term__nb_illustrated_notice')).order_by('-sum_notices')
    
    qs = qs[:count]
    
    results = [{
                "latitude": y["latitude"],
                "longitude": y["longitude"],
                "label": y["term__dbpedia_fields__label"],
                "sum_notices": y["sum_notices"],
                "dbpedia_uri": y["term__dbpedia_uri"]
                } for y in qs]
    
    return HttpResponse(content=json.dumps(results), mimetype='application/json')

def geo_search(request):
    
    lang = request.GET.get('lang', request.LANGUAGE_CODE)[:2]
    q = request.GET.get('term', None)
    count = request.GET.get('count', 20)
    
    qs = DbpediaGeo.objects.filter(term__dbpedia_fields__language_code=lang, term__dbpedia_fields__label__icontains=q, term__nb_illustrated_notice__gt=0)
    qs = qs.values('latitude','longitude','term__dbpedia_fields__label','term__dbpedia_uri')
    qs = qs.annotate(sum_notices=Sum('term__nb_illustrated_notice')).order_by('-sum_notices')[:count]
    
    results = [{
                "latitude": y["latitude"],
                "longitude": y["longitude"],
                "label": y["term__dbpedia_fields__label"],
                "sum_notices": y["sum_notices"],
                "dbpedia_uri": y["term__dbpedia_uri"]
                } for y in qs]
    results.sort(key=lambda y: y["label"])
    
    return HttpResponse(content=json.dumps(results), mimetype='application/json')

class BaseContributionView(TemplateView):
    
    template_name = "jocondelab/partial/contributed_item.html"
    
    def render_contribution(self, contribution, request):
        lang = request.LANGUAGE_CODE[:2]
        termdict = {
            "label": contribution.term.dbpedia_fields.get(language_code=lang).label,
            "dbpedia_uri": contribution.term.dbpedia_uri,
            "contribution_id": contribution.id,
            "li_style": "positive" if contribution.contribution_count > 0 else "null",
            "font_size": "%.1f"%(12. + .5 * max(0., min(12., contribution.contribution_count))),
            "vote_mode": (contribution.thesaurus is None)
        }
        return self.render_to_response({"term": termdict})
    
    def get(self, request):
        contribution_id = int(request.GET.get('contribution_id', None))
        return self.render_contribution(Contribution.objects.get(pk=contribution_id), request)

class ContributeView(BaseContributionView):
    
    def post(self, request):
        
        notice_id = request.POST.get('notice_id', None)
        lang = request.LANGUAGE_CODE[:2]
        thesaurus_label = request.POST.get('thesaurus_label', None)
        label = request.POST.get('label', None)
        
        sparqlTpl = """select distinct * where { ?s rdfs:label "%(label)s"@%(lang)s . 
            OPTIONAL { ?s dbpedia-owl:abstract ?a. FILTER(langMatches(lang(?a),"%(lang)s")) }. 
            OPTIONAL { ?s dbpedia-owl:thumbnail ?t }. 
            OPTIONAL { ?s dbpedia-owl:wikiPageRedirects ?r }.  
            OPTIONAL { ?r rdfs:label ?lr. FILTER(langMatches(lang(?lr),"%(lang)s")) }. 
            OPTIONAL { ?r dbpedia-owl:thumbnail ?tr }. 
            OPTIONAL { ?s dbpedia-owl:wikiPageDisambiguates ?d }. 
            OPTIONAL { ?d rdfs:label ?ld FILTER( langMatches(lang(?ld), "%(lang)s") ) }. 
            FILTER(!regex(?s, ":[^/]+$" ) && regex(?s, "^http://[^/]+/resource/")) }"""
        
        # First, test wikipedia_url
        dbpedia_uri = None
        r = requests.get('http://' + lang + '.wikipedia.org/wiki/' + label.replace(" ", "_"))
        if r.status_code == 200:
            # dbpedia FR sparql request
            data = {'query': sparqlTpl % {'label': label, 'lang':lang}, 'format': "application/sparql-results+json"}
            r = requests.get("http://fr.dbpedia.org/sparql", params=data, headers = {'content-type': "application/sparql-results+json"})
            if r.status_code != 200:
                return HttpResponseBadRequest()
            resp = r.json()
            if "results" in resp and "bindings" in resp["results"] and len(resp["results"]["bindings"])>0:
                dbpedia_uri = resp["results"]["bindings"][0]["s"]["value"]
        
        if not dbpedia_uri:
            return HttpResponseBadRequest()
        
        thobj = Thesaurus.objects.get(label=thesaurus_label) if thesaurus_label else None
        notobj = Notice.objects.get(id=notice_id)
        
        # History for the contribution term for this notice
        h = self.request.session.setdefault('contribution_history', {})
        if notice_id not in h:
            h[notice_id] = []
        h[notice_id].append(dbpedia_uri)
        self.request.session['contribution_history'] = h
        
        # Contributed Term is now validated and Dbpedia uris is regenerated by SPARQL Queries
        try:
            termobj, _ = ContributedTerm.objects.get_or_create(dbpedia_uri=dbpedia_uri)
        except:
            return HttpResponseBadRequest()
        controbj, created = Contribution.objects.get_or_create(term=termobj, thesaurus=thobj, notice=notobj, defaults={'contribution_count': 1})
        if not created:
            controbj.contribution_count += 1
            controbj.save()
        
        # Translated labels should also be regenerated from dbpedia.
        # Select labels from dppedia
        sparqlTpl = """select distinct * where { <%(uri)s> rdfs:label ?l . 
            OPTIONAL { <%(uri)s> dbpedia-owl:abstract ?a. FILTER(langMatches(lang(?l), lang(?a))) }. 
            OPTIONAL { <%(uri)s> dbpedia-owl:thumbnail ?t }. 
            OPTIONAL { <%(uri)s> dbpedia-owl:wikiPageRedirects ?r }.   
            OPTIONAL { ?r dbpedia-owl:thumbnail ?tr }. 
            OPTIONAL { <%(uri)s> dbpedia-owl:wikiPageDisambiguates ?d }.  
            FILTER(!regex(<%(uri)s>, ":[^/]+$" ) && regex(<%(uri)s>, "^http://[^/]+/resource/")) }"""
        
        # dbpedia FR sparql request
        data = {'query': sparqlTpl % {'uri': dbpedia_uri}, 'format': "application/sparql-results+json"}
        r = requests.get("http://fr.dbpedia.org/sparql", params=data, headers = {'content-type': "application/sparql-results+json"})
        if r.status_code == 200:
            resp = r.json()
            if "results" in resp and "bindings" in resp["results"] and len(resp["results"]["bindings"])>0:
                lang_list = [k[:2] for k,_ in settings.LANGUAGES]
                # We add label/abstract/thumbnail for all languages found for the dbpedia entry
                for b in resp["results"]["bindings"]:
                    # We assume that label is always here
                    lang = b["l"]["xml:lang"]
                    if lang in lang_list:
                        fieldsobj, created = ContributedFields.objects.get_or_create(term=termobj, dbpedia_uri=dbpedia_uri, language_code=lang, defaults={'label': label})
                        if created:
                            fieldsobj.label = b["l"]["value"]
                            if "t" in b:
                                fieldsobj.thumbnail = b["t"]["value"]
                            elif "tr" in b:
                                fieldsobj.thumbnail = b["tr"]["value"]
                            if "a" in b:
                                fieldsobj.abstract = b["a"]["value"]
                            fieldsobj.save()
                
            else:
                fieldsobj, created = ContributedFields.objects.get_or_create(term=termobj, dbpedia_uri=dbpedia_uri, language_code=lang, defaults={'label': label})
                # thumbnail, label, abstract
                if created:
                    fieldsobj.label = label
                    fieldsobj.save()
        
        return self.render_contribution(controbj, request)
    

class VoteView(BaseContributionView):
    
    vote_value = 0
    
    def post(self, request):
        contribution_id = int(request.POST.get('contribution_id', None))
        controbj = Contribution.objects.get(id=contribution_id)
        controbj.contribution_count += self.vote_value
        controbj.save()
        return self.render_contribution(controbj, request)
    