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

@author: rvelt
'''

from jocondelab.models import DbpediaYears, DbpediaGeo, DbpediaFields, ContributedTerm, ContributedFields, Contribution
from core.models import Notice, Thesaurus
import django.utils.simplejson as json
from django.core.paginator import Paginator
from django.http import HttpResponse
from django.template.response import TemplateResponse
from django.views.generic import TemplateView, DetailView
from django.db.models import Sum
from django.conf import settings
import requests

import logging
from django.http.response import HttpResponseBadRequest
from distutils.command.config import LANG_EXT
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]
        #dbpedia_uri = request.POST.get('dbpedia_uri', None) #TODO: Remove it and regenerate from Wikipedia/Dbpedia
        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)
    