from ..util.ui.uiutils import UIUtils
from ..util.sparqlutils import SPARQLUtils
from qgis.PyQt.QtGui import QStandardItem
from qgis.core import Qgis,QgsTask, QgsMessageLog

MESSAGE_CATEGORY = 'InstanceListQueryTask'

class InstanceListQueryTask(QgsTask):

    def __init__(self, description, triplestoreurl,dlg,treeNode,triplestoreconf,preferredlang="en"):
        super().__init__(description, QgsTask.CanCancel)
        self.exception = None
        self.triplestoreurl = triplestoreurl
        self.preferredlang=preferredlang
        self.dlg=dlg
        self.hasgeocount=0
        self.linkedgeocount=0
        self.triplestoreconf=triplestoreconf
        self.treeNode=treeNode
        self.queryresult={}

    def run(self):
        #QgsMessageLog.logMessage('Started task "{}"'.format(self.description()), MESSAGE_CATEGORY, Qgis.Info)
        typeproperty="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
        labelproperty="http://www.w3.org/2000/01/rdf-schema#label"
        if "typeproperty" in self.triplestoreconf:
            typeproperty=self.triplestoreconf["typeproperty"]
        if "labelproperty" in self.triplestoreconf:
            labelproperty=self.triplestoreconf["labelproperty"]
        nodetype=self.treeNode.data(257)
        labelpattern="OPTIONAL { ?con <"+labelproperty+"> ?label . }"
        if self.preferredlang!="en":
            labelpattern="OPTIONAL { ?con <"+labelproperty+" > ?label.\n FILTER langMatches(lang(?label),  \""+str(self.preferredlang)+"\") } OPTIONAL { ?class <"+labelproperty+"> ?label . }"
        geometryproperty=None
        if "geometryproperty" in self.triplestoreconf:
            if type(self.triplestoreconf["geometryproperty"]) is list:
                geometryproperty = self.triplestoreconf["geometryproperty"][0]
            else:
                geometryproperty = self.triplestoreconf["geometryproperty"]
        if nodetype==SPARQLUtils.collectionclassnode:
            #QgsMessageLog.logMessage('Started task "{}"'.format(
            #        "SELECT ?con ?label WHERE { " + str(
            #            self.treeNode.data(256)) + "http://www.w3.org/2000/01/rdf-schema#member ?con . "+str(labelpattern)+" }"), MESSAGE_CATEGORY, Qgis.Info)
            if "geometryproperty" in self.triplestoreconf:
                thequery="SELECT ?con ?label ?hasgeo WHERE {  <" + str(
                        self.treeNode.data(256)) + "> <http://www.w3.org/2000/01/rdf-schema#member> ?con .\n "+str(labelpattern)+"\n BIND(EXISTS { ""?con <" + str(
                            geometryproperty) + "> ?wkt"" } AS ?hasgeo) }"
            else:
                thequery="SELECT ?con ?label WHERE {  <" + str(
                        self.treeNode.data(256)) + "> <http://www.w3.org/2000/01/rdf-schema#member> ?con . "+str(labelpattern)+" }"
        elif nodetype==SPARQLUtils.linkedgeoclassnode:
            thequery = "SELECT ?con ?label ?hasgeo ?linkedgeo WHERE { ?con <" + typeproperty + "> <" + str(
                self.treeNode.data(256)) + "> . " + str(labelpattern) + " BIND(EXISTS {?con <" + str(
                geometryproperty) + "> ?wkt } AS ?hasgeo)  BIND(EXISTS {?con <" + str(
                self.treeNode.data(260)) + "> ?lgeo } AS ?linkedgeo)}"
        else:
            if "geometryproperty" in self.triplestoreconf:
                if isinstance(self.triplestoreurl, str):
                    #QgsMessageLog.logMessage('Started task "{}"'.format(
                    #    "SELECT ?con ?label ?hasgeo WHERE { ?con " + typeproperty + " " + str(
                    #       self.treeNode.data(
                    #            256)) + " . "+str(labelpattern)+" BIND(EXISTS {?con " + str(
                    #        geometryproperty) + " ?wkt } AS ?hasgeo)}"), MESSAGE_CATEGORY,
                    #    Qgis.Info)
                    thequery = "SELECT ?con ?label ?hasgeo WHERE { ?con <" + typeproperty + "> <" + str(
                        self.treeNode.data(256)) + "> . "+str(labelpattern)+" BIND(EXISTS {?con <" + str(
                        geometryproperty) + "> ?wkt } AS ?hasgeo)}"
                else:
                    thequery = "SELECT ?con ?label ?hasgeo WHERE { ?con <" + typeproperty + "> <" + str(
                        self.treeNode.data(256)) + "> . "+str(labelpattern)+" OPTIONAL { ?con <" + str(
                        geometryproperty) + "> ?hasgeo } }"
            else:
                #QgsMessageLog.logMessage('Started task "{}"'.format(
                #    "SELECT ?con ?label WHERE { ?con " + typeproperty + " " + str(
                #        self.treeNode.data(
                #            256)) + " . "+str(labelpattern)+" }"), MESSAGE_CATEGORY,
                #    Qgis.Info)
                thequery = "SELECT ?con ?label WHERE { ?con <" + typeproperty + "> <" + str(
                    self.treeNode.data(
                        256)) + "> . "+str(labelpattern)+" }"
        results = SPARQLUtils.executeQuery(self.triplestoreurl,thequery,self.triplestoreconf)
        if results!=False:
            for result in results["results"]["bindings"]:
                if result["con"]["value"] not in self.queryresult:
                    self.queryresult[result["con"]["value"]]={}
                if "hasgeo" in result and (result["hasgeo"]["value"]=="true" or result["hasgeo"]["value"]=="1" or (isinstance(result["hasgeo"]["value"],str) and result["hasgeo"]["value"]!="" and result["hasgeo"]["value"]!="0" and result["hasgeo"]["value"]!="false")):
                    #QgsMessageLog.logMessage('Started task "{}"'.format(result["hasgeo"]["value"]), MESSAGE_CATEGORY,Qgis.Info)
                    self.queryresult[result["con"]["value"]]["hasgeo"] = True
                    self.hasgeocount+=1
                else:
                    self.queryresult[result["con"]["value"]]["hasgeo"] = False
                if "linkedgeo" in result and (result["linkedgeo"]["value"]=="true" or result["linkedgeo"]["value"]=="1" or (isinstance(result["linkedgeo"]["value"],str) and result["linkedgeo"]["value"]!="" and result["linkedgeo"]["value"]!="0" and result["linkedgeo"]["value"]!="false")):
                    self.queryresult[result["con"]["value"]]["linkedgeo"] = True
                    self.linkedgeocount += 1
                else:
                    self.queryresult[result["con"]["value"]]["linkedgeo"] = False
                if "label" in result:
                    self.queryresult[result["con"]["value"]]["label"] = result["label"]["value"]+" ("+SPARQLUtils.labelFromURI(result["con"]["value"],self.triplestoreconf["prefixesrev"])+")"
                else:
                    self.queryresult[result["con"]["value"]]["label"]=SPARQLUtils.labelFromURI(result["con"]["value"],self.triplestoreconf["prefixesrev"])
        return True

    def finished(self, result):
        #QgsMessageLog.logMessage('Started task "{}"'.format(
        #    self.treeNode.text()+" "+str(self.hasgeocount)+" "+str(len(self.queryresult))), MESSAGE_CATEGORY, Qgis.Info)
        if self.treeNode.data(258)==None:
            self.treeNode.setData(str(len(self.queryresult)),258)
            self.treeNode.setText(self.treeNode.text()+" ["+str(len(self.queryresult))+"]")
        if(self.hasgeocount>0 and self.hasgeocount<len(self.queryresult)) and self.treeNode.data(257)!=SPARQLUtils.collectionclassnode and self.treeNode.data(257)!=SPARQLUtils.linkedgeoclassnode:
            self.treeNode.setIcon(UIUtils.halfgeoclassicon)
        elif self.hasgeocount==0 and self.treeNode.data(257)!=SPARQLUtils.collectionclassnode and self.treeNode.data(257)!=SPARQLUtils.linkedgeoclassnode:
            self.treeNode.setIcon(UIUtils.classicon)
        self.treeNode.setData(SPARQLUtils.instancesloadedindicator,259)
        for concept in self.queryresult:
            item = QStandardItem()
            item.setData(concept, 256)
            item.setText(self.queryresult[concept]["label"])
            if (self.treeNode.data(257)==SPARQLUtils.geoclassnode \
                    or self.treeNode.data(257)==SPARQLUtils.collectionclassnode
                or self.treeNode.data(257)==SPARQLUtils.linkedgeoclassnode) \
                    and self.queryresult[concept]["hasgeo"]:
                item.setData(SPARQLUtils.geoinstancenode,257)
                item.setIcon(UIUtils.geoinstanceicon)
                item.setToolTip("GeoInstance " + str(item.text()) + ": <br>" + SPARQLUtils.treeNodeToolTip)
            elif self.treeNode.data(257)==SPARQLUtils.linkedgeoclassnode and self.queryresult[concept]["linkedgeo"]:
                item.setData(SPARQLUtils.linkedgeoinstancenode,257)
                item.setIcon(UIUtils.linkedgeoinstanceicon)
                item.setToolTip("Linked GeoInstance " + str(item.text()) + ": <br>" + SPARQLUtils.treeNodeToolTip)
            else:
                item.setData(SPARQLUtils.instancenode,257)
                item.setIcon(UIUtils.instanceicon)
                item.setToolTip("Instance " + str(item.text()) + ": <br>" + SPARQLUtils.treeNodeToolTip)
            self.treeNode.appendRow(item)
