from django.db import IntegrityError
from django.db.models import Q
from django.http import HttpResponse, Http404
from django.views.decorators.csrf import csrf_exempt
from ldt.text.models import Annotation
from ldt.text.utils import TextSearch, generate_uuid
from oauth_provider.decorators import oauth_required
from urllib2 import urlparse
import lxml


## Filters the annotation depending on the request parameters
## Returns an xml containing the resulting annotations
def filter_annotation(request, uri=None, filter=None, limit=None, creator=None):
    query = Q()    
    
    if request.GET.get('uri'):
        query &= Q(uri=request.GET.get('uri'))
    if request.GET.get('creator'):
        query &= Q(creator=request.GET.get('creator'))

    annotlist = Annotation.objects.filter(query)
    
    if request.GET.get('filter') and len(request.GET.get('filter')) > 0:
        search = TextSearch()
        res = search.query("text", request.GET.get('filter'))        
        for r in res:
            annotlist.append(r)
    
    if request.GET.get('limit'):
        nb = request.GET.get('limit')[0]
        offset = request.GET.get('limit')[2]
        annotlist = annotlist[offset:]
        annotlist = annotlist[:nb]

    #create xml
    iri = lxml.etree.Element('iri')
    doc = lxml.etree.ElementTree(iri)
    
    for annot in annotlist:
        annot.serialize(iri)
        
    return HttpResponse(lxml.etree.tostring(doc, pretty_print=True), mimetype="text/xml;charset=utf-8")


## Creates an annotation from a urlencoded xml content
## Returns an xml-structured annotation
@oauth_required
@csrf_exempt
def create_annotation(request):
    cont = request.POST["content"]
    doc = lxml.etree.fromstring(cont)
    
    id_nodes = doc.xpath("/iri/text-annotation/id/text()")
    if id_nodes:
        id = unicode(id_nodes[0])
    else:
        id = generate_uuid()
        
    uri = unicode(doc.xpath("/iri/text-annotation/uri/text()")[0])

    ltags = list(set([unicode(tag.text).lower().strip() for tag in doc.xpath("/iri/text-annotation/tags/tag")]))
    tags = ",".join(ltags)
    if len(ltags) == 1:
        tags += ","
    
    
    title_nodes = doc.xpath("/iri/text-annotation/content/title/text()")
    if title_nodes:
        title = unicode(title_nodes[0])
    else:
        title = None
    desc_nodes = doc.xpath("/iri/text-annotation/content/description/text()")
    if desc_nodes:
        desc = unicode(desc_nodes[0])
    else:
        desc = None
    text_nodes = doc.xpath("/iri/text-annotation/content/text/text()")
    if text_nodes:
        text = unicode(text_nodes[0])
    else:
        text = None
    color_nodes = doc.xpath("/iri/text-annotation/content/color/text()")
    if color_nodes:
        color = unicode(color_nodes[0])
    else:
        color = None
    
    creator_nodes = doc.xpath("/iri/text-annotation/meta/creator/text()")
    if creator_nodes:
        creator = unicode(creator_nodes[0])
    else:
        creator = None
    contributor_nodes = doc.xpath("/iri/text-annotation/meta/contributor/text()")
    if contributor_nodes:
        contributor = unicode(contributor_nodes[0])
    else:
        contributor = None

    try:
        annotation = Annotation.create_annotation(external_id=id, uri=uri, tags=tags, title=title, description=desc, text=text, color=color, creator=creator, contributor=contributor)
        annotation.save()
        return HttpResponse(lxml.etree.tostring(annotation.serialize(), pretty_print=True), mimetype="text/xml;charset=utf-8")
    except IntegrityError:
        return HttpResponse(status=409)

    
    
## Gets an annotation from its id
## Returns the xml-structured annotation
def get_annotation(request, id):
    try:
        annot = Annotation.objects.get(external_id=id)
    except Annotation.DoesNotExist:
        raise Http404

    doc = annot.serialize()

    return HttpResponse(lxml.etree.tostring(doc, pretty_print=True), mimetype="text/xml;charset=utf-8")


## Deletes an annotation (from its id)
## Returns an empty xml-structured annotation
@oauth_required
@csrf_exempt
def delete_annotation(request, id):
    try:
        annot = Annotation.objects.get(external_id=id)
        annot.delete()
    except Annotation.DoesNotExist:
        raise Http404
    
    return HttpResponse("")


## Updates the content of an annotation
## Returns the xml-structured updated annotation
@oauth_required
@csrf_exempt
def update_annotation(request, id):
    
    put_data = {}
    if request.GET != {}:
        put_data = request.GET.copy()
    elif request.raw_post_data is not None:
        for k, v in urlparse.parse_qs(request.raw_post_data).iteritems():
            if len(v) > 1:
                for item in v:
                    put_data[k] = item
            else:
                put_data[k] = v[0]
    
    try:
        annot = Annotation.objects.get(external_id=id)
    except Annotation.DoesNotExist:
        raise Http404
    
    cont = put_data['content']
    doc = lxml.etree.fromstring(cont)
    
    uri = doc.xpath("/iri/text-annotation/uri/text()")
    if uri != [] and annot.uri != uri[0]:
        annot.uri = unicode(uri[0])
    
    tags_nodes = doc.xpath("/iri/text-annotation/tags")
    
    if len(tags_nodes) > 0:
        tags = list(set([unicode(tag.text).lower().strip() for tag in doc.xpath("/iri/text-annotation/tags/tag")]))
        tags_str = ",".join(tags)
        if len(tags) == 1:
            tags_str += ","
        annot.tags = tags_str
                    
    title = doc.xpath("/iri/text-annotation/content/title/text()")
    if title and annot.title != title[0]:
        annot.title = unicode(title[0])
    desc = doc.xpath("/iri/text-annotation/content/description/text()")
    if desc and annot.description != desc[0]:
        annot.description = unicode(desc[0])
    text = doc.xpath("/iri/text-annotation/content/text/text()")
    if text and annot.text != text[0]:
        annot.text = unicode(text[0])
    color = doc.xpath("/iri/text-annotation/content/color/text()")
    if color and annot.color != color[0]:
        annot.color = unicode(color[0])
    
    contributor = doc.xpath("/iri/text-annotation/meta/contributor/text()")
    if contributor and annot.contributor != contributor[0]:
        annot.contributor = unicode(contributor[0])
    update_date = doc.xpath("/iri/text-annotation/meta/modified/text()")
    if update_date and annot.update_date != update_date[0]:
        annot.update_date = unicode(update_date[0])

    annot.save()

    return HttpResponse(lxml.etree.tostring(annot.serialize(), pretty_print=True), mimetype="text/xml;charset=utf-8")

    
