'''
ARCHES - a program developed to inventory and manage immovable cultural heritage.
Copyright (C) 2013 J. Paul Getty Trust and World Monuments Fund

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
'''

import urllib2
from django.utils.translation import ugettext as _
from arches.app.models.models import DValueType
from arches.app.models.concept import Concept, ConceptValue
from arches.app.models.system_settings import settings
from arches.app.utils.betterJSONSerializer import JSONSerializer, JSONDeserializer
from SPARQLWrapper import SPARQLWrapper, JSON
from abstract_provider import Abstract_Provider
from rdflib.namespace import SKOS, DCTERMS

class AAT_Provider(Abstract_Provider):

    def __init__(self, **kwargs):
        super(AAT_Provider, self).__init__('http://vocab.getty.edu/sparql.json', **kwargs)
        
        self.name = _('Getty AAT')        
        self.setReturnFormat(JSON)     

    def get_concepts(self, uris):  
        """
        Get a list of concepts given a list of AAT uris like http://vocab.getty.edu/aat/300380087

        """  

        default_lang = settings.LANGUAGE_CODE
        dcterms_identifier_type = DValueType.objects.get(valuetype=str(DCTERMS.identifier).replace(str(DCTERMS), ''), namespace = 'dcterms')

        concepts = []    
        langs = []   
        for lang in self.allowed_languages:
            # the AAT expects language codes to be all lower case
            langs.append('\"%s\"' % (lang.lower()))
        for uri in uris.split(','):
            query = """
                SELECT ?value ?type WHERE {
                  {
                    <%s> skos:prefLabel ?value .
                    BIND('prefLabel' AS ?type)
                  }
                  UNION
                  {
                    <%s> skos:scopeNote [rdf:value ?value] .
                    BIND('scopeNote' AS ?type)
                  }
                  FILTER (lang(?value) in (%s)) 
                }""" % (uri, uri, ','.join(langs))
            results = self.perform_sparql_query(query)

            if len(results["results"]["bindings"]) > 0 :
                concept = Concept()
                concept.nodetype = 'Concept'
                for result in results["results"]["bindings"]:
                    concept.addvalue({
                        'type': result["type"]["value"],
                        'value': result["value"]["value"],
                        'language': result["value"]["xml:lang"]
                    }) 
                concept.addvalue({'value':uri, 'language': settings.LANGUAGE_CODE, 'type': dcterms_identifier_type.valuetype, 'category': dcterms_identifier_type.category})
                concepts.append(concept)
            else:
                raise Exception(_("<strong>Error in SPARQL query:</strong><br>Test this query directly by pasting the query below into the Getty's own SPARQL endpoint at <a href='http://vocab.getty.edu/sparql' target='_blank'>http://vocab.getty.edu/sparql</a><i><pre>%s</pre></i>Query returned 0 results, please check the query for errors.  You may need to add the appropriate languages into the database for this query to work<br><br>") % (query.replace('<', '&lt').replace('>', '&gt')))

        return concepts

    def search_for_concepts(self, terms):
        query = """PREFIX dct: <http://purl.org/dc/terms/>
            PREFIX gvp: <http://vocab.getty.edu/ontology#>
            PREFIX gvp_lang: <http://vocab.getty.edu/language/>
            PREFIX luc: <http://www.ontotext.com/owlim/lucene#>
            PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
            PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
            PREFIX skosxl: <http://www.w3.org/2008/05/skos-xl#>
            SELECT ?Subject ?Term ?ScopeNote {
                ?Subject luc:term '%s*'; a skos:Concept; skos:inScheme aat:.
                #?Subject rdf:type c.
                #?typ rdfs:subClassOf gvp:Subject; rdfs:label ?Type.
                optional {?Subject (gvp:prefLabelGVP | skos:prefLabel) [skosxl:literalForm ?Term]}
                #optional {?Subject gvp:parentStringAbbrev ?Parents}
                optional {?Subject skos:scopeNote [dct:language gvp_lang:en; rdf:value ?ScopeNote]}}""" % (terms)

        results = self.perform_sparql_query(query)
        return results

    def perform_sparql_query(self, query):
        self.setQuery(query)

        #print query
        #return HttpResponse(self.endpoint + '?' + self._getRequestEncodedParameters(("query", self.queryString)))

        req = urllib2.Request(self.endpoint + '?' + self._getRequestEncodedParameters(("query", self.queryString)))
        req.add_header("Accept", "application/sparql-results+json")
        f = urllib2.urlopen(req)
        return JSONDeserializer().deserialize(f.read())