# -*- coding: utf-8 -*-
"""
/***************************************************************************
 SPAQLunicornDialog
                                 A QGIS plugin
 This plugin adds a GeoJSON layer from a Wikidata SPARQL query.
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                             -------------------
        begin                : 2019-10-28
        git sha              : $Format:%H$
        copyright            : (C) 2019 by SPARQL Unicorn
        email                : rse@fthiery.de
 ***************************************************************************/

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

import os
import re
import json

from qgis.PyQt import uic, QtWidgets
from qgis.core import QgsMessageLog, Qgis,QgsApplication
from qgis.PyQt.QtGui import QStandardItemModel
from qgis.PyQt.QtCore import QItemSelectionModel
from qgis.PyQt.QtGui import QIcon, QStandardItem
from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtWidgets import QMessageBox, QStyle, QProgressDialog, QSizePolicy
from rdflib.plugins.sparql import prepareQuery

from ..util.ui.uiutils import UIUtils
from .aboutdialog import AboutDialog
from .preferencesdialog import PreferencesDialog
from ..tasks.classtreequerytask import ClassTreeQueryTask
from ..tasks.geocollectionsquerytask import GeoCollectionsQueryTask
from ..tasks.geoconceptsquerytask import GeoConceptsQueryTask
from ..tasks.querylayertask import QueryLayerTask
from .menu.conceptcontextmenu import ConceptContextMenu
from .menu.tabcontextmenu import TabContextMenu
from ..dialogs.convertcrsdialog import ConvertCRSDialog
from ..dialogs.triplestoredialog import TripleStoreDialog
from ..dialogs.graphvalidationdialog import GraphValidationDialog
from ..dialogs.triplestorequickadddialog import TripleStoreQuickAddDialog
from ..dialogs.searchdialog import SearchDialog
from ..dialogs.valuemappingdialog import ValueMappingDialog
from ..dialogs.convertlayerdialog import ConvertLayerDialog
from ..dialogs.bboxdialog import BBOXDialog
from ..tabs.enrichmenttab import EnrichmentTab
from ..tabs.interlinkingtab import InterlinkingTab
from ..util.ui.tooltipplaintext import ToolTipPlainText
from ..util.ui.sparqlhighlighter import SPARQLHighlighter
from ..util.ui.classtreesortproxymodel import ClassTreeSortProxyModel
from ..util.sparqlutils import SPARQLUtils

# This loads your .ui file so that PyQt can populate your plugin with the elements from Qt Designer
FORM_CLASS, _ = uic.loadUiType(os.path.join(
    os.path.dirname(__file__), 'ui/sparql_unicorn_dialog_base.ui'))

MESSAGE_CATEGORY = 'SPARQLUnicornDialog'

##
#  @brief The main dialog window of the SPARQLUnicorn QGIS Plugin.
class SPARQLunicornDialog(QtWidgets.QMainWindow, FORM_CLASS):
    ## The triple store configuration file
    triplestoreconf = None
    ## Prefix map
    prefixes = None

    """QGIS Plugin Implementation."""
    loadedfromfile = False

    enrichtab = None

    currentgraph = None

    interlinktab = None

    conceptList = None

    completerClassList = None

    columnvars = {}

    def __init__(self, triplestoreconf={}, prefixes=[], addVocabConf={}, autocomplete={},
                 prefixstore={"normal": {}, "reversed": {}}, savedQueriesJSON={}, maindlg=None, parent=None):
        """Constructor."""
        super(SPARQLunicornDialog, self).__init__(parent)
        self.setupUi(self)
        self.setWindowIcon(UIUtils.sparqlunicornicon)
        self.setCentralWidget(self.tabWidget)
        self.prefixes = prefixes
        self.maindlg = maindlg
        self.savedQueriesJSON = savedQueriesJSON
        self.enrichtab = EnrichmentTab(self)
        self.interlinktab = InterlinkingTab(self)
        self.addVocabConf = addVocabConf
        self.autocomplete = autocomplete
        self.prefixstore = prefixstore
        self.triplestoreconf = triplestoreconf
        self.layercount=0
        self.geoTreeView.customContextMenuRequested.connect(self.onContext)
        self.geoTreeViewModel = QStandardItemModel()
        self.geoTreeView.setModel(self.geoTreeViewModel)
        self.classTreeView.customContextMenuRequested.connect(self.onContext4)
        self.featureCollectionClassListModel = QStandardItemModel()
        self.geometryCollectionClassListModel = QStandardItemModel()
        self.classTreeViewModel = QStandardItemModel()
        self.quickAddTripleStore.setIcon(UIUtils.linkeddataicon)
        self.geoTreeViewProxyModel = ClassTreeSortProxyModel(self.geoTreeViewModel)
        self.featureCollectionProxyModel = ClassTreeSortProxyModel(self.featureCollectionClassListModel)
        self.geometryCollectionProxyModel = ClassTreeSortProxyModel(self.geometryCollectionClassListModel)
        self.classTreeViewProxyModel = ClassTreeSortProxyModel(self.classTreeViewModel)
        self.classTreeView.setModel(self.classTreeViewProxyModel)
        self.geoTreeView.setModel(self.geoTreeViewProxyModel)
        self.geoTreeViewModel.clear()
        self.addLayerButton.clicked.connect(self.create_unicorn_layer)
        self.comboBox.currentIndexChanged.connect(self.endpointselectaction)
        self.detectMapping.hide()
        self.rootNode = self.geoTreeViewModel.invisibleRootItem()
        self.featureCollectionClassList.setModel(self.featureCollectionProxyModel)
        self.featureCollectionClassList.customContextMenuRequested.connect(self.onContext2)
        self.featureCollectionClassListModel.clear()
        self.geometryCollectionClassList.setModel(self.geometryCollectionProxyModel)
        self.geometryCollectionClassList.customContextMenuRequested.connect(self.onContext3)
        self.geometryCollectionClassListModel.clear()
        self.featureCollectionClassList.doubleClicked.connect(self.createLayerFromTreeEntry)
        self.geometryCollectionClassList.doubleClicked.connect(self.createLayerFromTreeEntry)
        self.geoTreeView.doubleClicked.connect(self.createLayerFromTreeEntry)
        self.classTreeView.doubleClicked.connect(self.createLayerFromTreeEntry)
        self.filterConcepts.textChanged.connect(lambda: self.currentProxyModel.setFilterRegExp(self.filterConcepts.text()))
        self.inp_sparql.hide()
        self.inp_sparql2 = ToolTipPlainText(self.queryTab, self.triplestoreconf, self.comboBox, self.columnvars,
                                            self.prefixes, self.autocomplete,self.triplestoreconf[self.comboBox.currentIndex()])
        self.gridLayout.addWidget(self.inp_sparql2,5,0,1,4)
        self.gridLayout_7.addWidget(self.enrichTableResult,4,1,1,3)
        self.inp_sparql2.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.inp_sparql2.document().defaultFont().setPointSize(16)
        self.inp_sparql2.setPlainText("SELECT ?item ?lat ?lon WHERE {\n ?item ?b ?c .\n} LIMIT 10")
        self.inp_sparql2.columnvars = {}
        self.inp_sparql2.textChanged.connect(self.validateSPARQL)
        self.sparqlhighlight = SPARQLHighlighter(self.inp_sparql2)
        self.currentContext=self.geoTreeView
        self.currentProxyModel=self.geoTreeViewProxyModel
        self.currentContextModel=self.geoTreeViewModel
        self.enrichTableResult.hide()
        self.queryTemplates.currentIndexChanged.connect(self.changeQueryTemplate)
        self.actionRDF_Resource_Settings.setIcon(UIUtils.linkeddataicon)
        self.actionRDF_Resource_Settings.triggered.connect(lambda: TripleStoreDialog(self.triplestoreconf, self.prefixes, self.prefixstore,self.comboBox).exec())
        self.actionPreferences.triggered.connect(lambda: PreferencesDialog().exec())
        self.actionPreferences.setVisible(False)
        self.actionConvert_RDF_Data.setIcon(UIUtils.rdffileicon)
        self.actionSearch_Concept_for_Query.setIcon(UIUtils.searchclassicon)
        self.actionSearch_Concept_for_Query.triggered.connect(lambda: self.buildSearchDialog(-1, -1, -1, self.inp_sparql2, True, True))
        self.actionConvert_RDF_Data.triggered.connect(lambda: ConvertCRSDialog(self.triplestoreconf, self.maindlg, self).exec())
        self.actionLayer_Column_as_Variable.triggered.connect(self.inp_sparql2.createVarInputDialog)
        self.actionLayer_Column_as_Variable.setIcon(UIUtils.columnasvaricon)
        self.actionConvert_QGIS_Layer_To_RDF.triggered.connect(lambda: ConvertLayerDialog(self.triplestoreconf, self.maindlg.prefixes, self.maindlg, self).exec())
        self.actionConvert_QGIS_Layer_To_RDF.setIcon(UIUtils.featurecollectionToRDFicon)
        self.actionValidate_RDF_Data.triggered.connect(lambda: GraphValidationDialog(self.triplestoreconf, self.maindlg, self).exec())
        self.actionValidate_RDF_Data.setIcon(UIUtils.validationicon)
        self.actionConstraint_By_BBOX.triggered.connect(lambda: BBOXDialog(self.inp_sparql2, self.triplestoreconf, self.comboBox.currentIndex()).exec())
        self.actionConstraint_By_BBOX.setIcon(UIUtils.bboxicon)
        self.actionPreferences.setIcon(QIcon(self.style().standardIcon(getattr(QStyle, 'SP_ComputerIcon'))))
        self.actionAbout.setIcon(QIcon(self.style().standardIcon(getattr(QStyle, 'SP_MessageBoxInformation'))))
        self.actionAbout.triggered.connect(lambda: AboutDialog().exec())
        self.tripleStoreInfoButton.setIcon(QIcon(self.style().standardIcon(getattr(QStyle,'SP_MessageBoxInformation'))))
        self.tripleStoreInfoButton.clicked.connect(self.tripleStoreInfoDialog)
        self.loadQuery.clicked.connect(self.loadQueryFunc)
        self.saveQueryButton.clicked.connect(self.saveQueryFunc)
        self.geoTreeView.selectionModel().currentChanged.connect(self.conceptSelectAction)
        self.classTreeView.selectionModel().currentChanged.connect(self.conceptSelectAction)
        self.conceptViewTabWidget.currentChanged.connect(self.tabchanged)
        self.conceptViewTabWidget.customContextMenuRequested.connect(lambda position: TabContextMenu("Menu", self.conceptViewTabWidget,self.currentContext.viewport().mapToGlobal(position),self.triplestoreconf[self.comboBox.currentIndex()]))
        self.featureCollectionClassList.selectionModel().currentChanged.connect(self.collectionSelectAction)
        self.geometryCollectionClassList.selectionModel().currentChanged.connect(self.collectionSelectAction)
        self.quickAddTripleStore.clicked.connect(lambda: TripleStoreQuickAddDialog(self.triplestoreconf, self.prefixes, self.prefixstore,
                                                                 self.comboBox,self.maindlg,self).exec())
        self.show()

    def changeQueryTemplate(self):
        self.inp_sparql2.setPlainText(self.queryTemplates.itemData(self.queryTemplates.currentIndex()))
        self.conceptSelectAction()

    def tripleStoreInfoDialog(self):
        msgBox = QMessageBox()
        msgBox.setWindowTitle("RDF Resource Information")
        msgBox.setWindowIcon(QIcon(self.style().standardIcon(getattr(QStyle,'SP_MessageBoxInformation'))))
        thetext="<html><h3>Information about "+str(self.triplestoreconf[self.comboBox.currentIndex()]["name"])+"</h3><table border=1 cellspacing=0><tr><th>Information</th><th>Value</th></tr>"
        thetext+="<tr><td>Name</td><td>"+str(self.triplestoreconf[self.comboBox.currentIndex()]["name"])+"</td></tr>"
        thetext+="<tr><td>Type</td><td>"+str(self.triplestoreconf[self.comboBox.currentIndex()]["type"])+"</td></tr>"
        thetext+="<tr><td>Endpoint</td><td><a href=\""+str(self.triplestoreconf[self.comboBox.currentIndex()]["resource"]["url"])+"\">"+str(self.triplestoreconf[self.comboBox.currentIndex()]["resource"]["url"])+"</a></td></tr>"
        thetext+="<tr><td>Type Property</td><td><a href=\""+str(self.triplestoreconf[self.comboBox.currentIndex()]["typeproperty"])+"\">"+str(self.triplestoreconf[self.comboBox.currentIndex()]["typeproperty"])+"</a></td></tr>"
        thetext+="<tr><td>Label Property</td><td><a href=\""+str(self.triplestoreconf[self.comboBox.currentIndex()]["labelproperty"])+"\">"+str(self.triplestoreconf[self.comboBox.currentIndex()]["labelproperty"])+"</a></td></tr>"
        if "geometryproperty" in self.triplestoreconf[self.comboBox.currentIndex()]:
            thetext+= "<tr><td>Geometry Property</td><td><a href=\"" + str(self.triplestoreconf[self.comboBox.currentIndex()]["geometryproperty"]) + "\">" + str(self.triplestoreconf[self.comboBox.currentIndex()]["geometryproperty"]) + "</a></td></tr>"
        geoprops=""
        if "geoobjproperty" in self.triplestoreconf[self.comboBox.currentIndex()]:
            geoprops += "<tr><td>Detected Geom Properties</td><td><a href=\"" + str(
                self.triplestoreconf[self.comboBox.currentIndex()]["geoobjproperty"]) + "\">" + str(
                self.triplestoreconf[self.comboBox.currentIndex()]["geoobjproperty"]) + "</a></td></tr>"
        thetext+=geoprops
        if "geoclasses" in self.triplestoreconf[self.comboBox.currentIndex()]:
            thetext += "<tr><td>Detected Geometry Classes</td><td><a href=\"" + str(
                self.triplestoreconf[self.comboBox.currentIndex()]["geoclasses"].keys()) + "\">" + str(
                self.triplestoreconf[self.comboBox.currentIndex()]["geoclasses"].keys()) + "</a></td></tr>"
        thetext+="</html>"
        msgBox.setText(thetext)
        msgBox.exec()

    def loadQueryFunc(self):
        if "url" in self.triplestoreconf[self.comboBox.currentIndex()] and self.triplestoreconf[self.comboBox.currentIndex()]["resource"]["url"] in self.savedQueriesJSON:
            self.inp_sparql2.setPlainText(
                self.savedQueriesJSON[self.triplestoreconf[self.comboBox.currentIndex()]["resource"]["url"]][
                    self.savedQueries.currentIndex()]["query"])

    def saveQueryFunc(self):
        queryName = self.saveQueryName.text()
        if queryName is not None and queryName != "":
            __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
            if "url" in self.triplestoreconf[self.comboBox.currentIndex()]["resource"] and not self.triplestoreconf[self.comboBox.currentIndex()]["resource"]["url"] in self.savedQueriesJSON:
                self.savedQueriesJSON[self.triplestoreconf[self.comboBox.currentIndex()]["resource"]["url"]] = []
            self.savedQueriesJSON[self.triplestoreconf[self.comboBox.currentIndex()]["resource"]["url"]].append(
                {"label": queryName, "query": self.inp_sparql2.toPlainText()})
            self.savedQueries.addItem(queryName)
            f = open(os.path.join(__location__, 'savedqueries.json'), "w")
            f.write(json.dumps(self.savedQueriesJSON))
            f.close()

    def onContext(self,position):
        self.currentContext=self.geoTreeView
        self.currentContextModel = self.geoTreeViewModel
        self.currentProxyModel = self.geoTreeViewProxyModel
        self.createMenu(position)

    def onContext2(self, position):
        self.currentContext=self.featureCollectionClassList
        self.currentContextModel = self.featureCollectionClassListModel
        self.currentProxyModel = self.featureCollectionProxyModel
        self.createMenu(position)

    def onContext3(self, position):
        self.currentContext = self.geometryCollectionClassList
        self.currentContextModel = self.geometryCollectionClassListModel
        self.currentProxyModel = self.geometryCollectionProxyModel
        self.createMenu(position)

    def createMenu(self,position):
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        if self.currentContextModel.itemFromIndex(curindex)!=None:
            ConceptContextMenu(self,self.triplestoreconf[self.comboBox.currentIndex()],self.prefixes,position,self.currentContext,self.currentContextModel.itemFromIndex(curindex),self.queryResultLanguageCBox.currentText())


    ## Creates a layer from the result of the given SPARQL unicorn query.
    #  @param self The object pointer.
    def create_unicorn_layer(self):
        endpointIndex = self.comboBox.currentIndex()
        query = self.inp_sparql2.toPlainText()
        missingmandvars = []
        for mandvar in self.triplestoreconf[endpointIndex]["mandatoryvariables"]:
            if mandvar not in query:
                missingmandvars.append("?" + mandvar)
        if missingmandvars != [] and not self.allownongeo.isChecked():
            msgBox = QMessageBox()
            msgBox.setWindowTitle("Mandatory variables missing!")
            msgBox.setText("The SPARQL query is missing the following mandatory variables: " + str(missingmandvars))
            msgBox.exec()
            return
        progress = QProgressDialog(
                "Querying layer from " + str(self.triplestoreconf[endpointIndex]["name"]) + "...", "Abort", 0, 0,
                self)
        progress.setWindowTitle("Query layer")
        progress.setWindowIcon(UIUtils.sparqlunicornicon)
        progress.setWindowModality(Qt.WindowModal)
        progress.setCancelButton(None)
        progress.show()
        queryprefixes = []
        prefixestoadd = ""
        for line in query.split("\n"):
            if line.startswith("PREFIX"):
                queryprefixes.append(line[line.find("http"):].replace(">", ""))
                url = line[line.find("http"):].replace(">", "")
        for endpoint in self.triplestoreconf[endpointIndex]["prefixes"]:
            if not self.triplestoreconf[endpointIndex]["prefixes"][endpoint] in queryprefixes:
                prefixestoadd += "PREFIX " + endpoint + ": <" + self.triplestoreconf[endpointIndex]["prefixes"][
                    endpoint] + "> \n"
        self.qtask = QueryLayerTask("Querying QGIS Layer from " + str(self.triplestoreconf[endpointIndex]["resource"]),
                                    None,
                                    self.triplestoreconf[endpointIndex]["resource"],
                                    prefixestoadd + query, self.triplestoreconf[endpointIndex],
                                    True, self.inp_label.text(), progress)
        QgsApplication.taskManager().addTask(self.qtask)
        # self.close()


    ## Gets a set of geometric concepts from the selected triple store.
    #  @param self The object pointer.
    #  @param triplestoreurl the url of the SPARQL endpoint
    #  @param query the query to execute
    #  @param queryvar the queryvariable returning the geoconcepts
    #  @param graph the graph to query if to query from a file
    #  @param getlabels indicates whether to also query labels for the returned geoconcepts
    def getGeoConcepts(self, triplestoreurl, query, queryvar, graph, getlabels, examplequery):
        viewlist = []
        resultlist = []
        if graph != None:
            results = graph.query(query)
            self.autocomplete["completerClassList"] = {}
            for row in results:
                viewlist.append(str(row[0]))
                self.autocomplete["completerClassList"][row] = str(row[0])
            self.conceptViewTabWidget.setTabText(0, "GeoConcepts (" + str(len(viewlist)) + ")")
            return viewlist
        self.qtask = GeoConceptsQueryTask("Querying GeoConcepts from " + str(triplestoreurl),
                                          triplestoreurl,
                                          query, self.triplestoreconf[self.comboBox.currentIndex()],
                                          self.inp_sparql2, queryvar, getlabels, self.layercount,
                                          self.geoTreeViewModel, examplequery, self.geoTreeView,
                                          self.autocomplete, self,self.queryResultLanguageCBox.currentText())
        QgsApplication.taskManager().addTask(self.qtask)

    def getClassTree(self):
        self.classTreeViewModel.clear()
        item2 = QStandardItem()
        item2.setText("Loading...")
        self.classTreeViewModel.appendRow(item2)
        if self.triplestoreconf[self.comboBox.currentIndex()]["type"] == "sparlendpoint":
            self.qtaskctree = ClassTreeQueryTask(
                "Getting classtree for " + str(self.triplestoreconf[self.comboBox.currentIndex()]["resource"]),
                self.triplestoreconf[self.comboBox.currentIndex()]["resource"],
                self, self.classTreeViewModel.invisibleRootItem(),
                self.triplestoreconf[self.comboBox.currentIndex()])
        elif self.triplestoreconf[self.comboBox.currentIndex()]["type"] == "file":
            self.qtaskctree = ClassTreeQueryTask(
                "Getting classtree...",
                self.currentgraph,
                self, self.classTreeViewModel.invisibleRootItem(),
                self.triplestoreconf[self.comboBox.currentIndex()])
        else:
            self.qtaskctree = ClassTreeQueryTask(
                "Getting classtree for " + str(self.triplestoreconf[self.comboBox.currentIndex()]["resource"]),
                self.triplestoreconf[self.comboBox.currentIndex()]["resource"],
                self, self.classTreeViewModel.invisibleRootItem(),
                self.triplestoreconf[self.comboBox.currentIndex()])
        QgsApplication.taskManager().addTask(self.qtaskctree)

    def getGeoCollectionInstances(self, triplestoreurl, query, queryvar, graph, featureOrGeoCollection, examplequery):
        viewlist = []
        resultlist = []
        if graph != None:
            results = graph.query(query)
            self.autocomplete["completerClassList"] = {}
            for row in results:
                viewlist.append(str(row[0]))
                self.autocomplete["completerClassList"][row] = str(row[0])
            return viewlist
        #QgsMessageLog.logMessage('Started task "{}"'.format(str(query)), "SPARQL Unicorn", Qgis.Info)
        if featureOrGeoCollection:
            self.qtaskfeature = GeoCollectionsQueryTask("Querying FeatureCollections from " + str(triplestoreurl),
                                                        triplestoreurl,
                                                        query, self.triplestoreconf[self.comboBox.currentIndex()],
                                                        self.inp_sparql2, queryvar, "label", featureOrGeoCollection,
                                                        self.layercount,
                                                        self.featureCollectionClassListModel, examplequery,
                                                        self.featureCollectionClassList,
                                                        self.autocomplete, self)
            QgsApplication.taskManager().addTask(self.qtaskfeature)
        else:
            self.qtaskgeos = GeoCollectionsQueryTask("Querying GeometryCollections from " + str(triplestoreurl),
                                                     triplestoreurl,
                                                     query, self.triplestoreconf[self.comboBox.currentIndex()],
                                                     self.inp_sparql2, queryvar, "label", featureOrGeoCollection,
                                                     self.layercount,
                                                     self.geometryCollectionClassListModel, examplequery,
                                                     self.geometryCollectionClassList,
                                                     self.autocomplete, self)
            QgsApplication.taskManager().addTask(self.qtaskgeos)

    ## Selects a SPARQL endpoint and changes its configuration accordingly.
    #  @param self The object pointer.
    def endpointselectaction(self):
        endpointIndex = self.comboBox.currentIndex()
        self.queryTemplates.clear()
        self.filterConcepts.setText("")
        #QgsMessageLog.logMessage('Started task "{}"'.format(self.triplestoreconf[endpointIndex]), "SPARQLUnicorn",
                                 #Qgis.Info)
        self.geoTreeViewModel.clear()
        self.classTreeViewModel.clear()
        self.geometryCollectionClassListModel.clear()
        self.featureCollectionClassListModel.clear()
        self.conceptViewTabWidget.setTabText(0, "GeoConcepts")
        self.conceptViewTabWidget.setTabText(1, "FeatureCollections")
        self.conceptViewTabWidget.setTabText(2, "GeometryCollections")
        self.conceptViewTabWidget.setTabText(3, "ClassTree")
        self.savedQueries.clear()
        if "prefixesrev" not in self.triplestoreconf[endpointIndex] and "prefixes" in self.triplestoreconf[
            endpointIndex] and self.triplestoreconf[endpointIndex]["prefixes"] != None and \
                self.triplestoreconf[endpointIndex]["prefixes"] != "":
            self.triplestoreconf[endpointIndex]["prefixesrev"] = SPARQLUtils.invertPrefixes(
                self.triplestoreconf[endpointIndex]["prefixes"])
        if "resource" in self.triplestoreconf[endpointIndex] and "url" in self.triplestoreconf[endpointIndex]["resource"] and not isinstance(self.triplestoreconf[endpointIndex]["resource"]["url"] ,list) and self.triplestoreconf[endpointIndex][
            "resource"]["url"] in self.savedQueriesJSON:
            for item in self.savedQueriesJSON[self.triplestoreconf[endpointIndex]["resource"]["url"]]:
                self.savedQueries.addItem(item["label"])
        if "resource" in self.triplestoreconf[endpointIndex] and self.triplestoreconf[endpointIndex][
            "resource"] != "" and (
                not "staticconcepts" in self.triplestoreconf[endpointIndex] or "staticconcepts" in self.triplestoreconf[
            endpointIndex] and self.triplestoreconf[endpointIndex]["staticconcepts"] == []) and "geoconceptquery" in \
                self.triplestoreconf[endpointIndex] and self.triplestoreconf[endpointIndex]["geoconceptquery"] != "":
            item = QStandardItem()
            item.setText("Loading...")
            self.geoTreeViewModel.appendRow(item)
            item2 = QStandardItem()
            item2.setText("Loading...")
            self.classTreeViewModel.appendRow(item)
            if "examplequery" in self.triplestoreconf[endpointIndex]:
                self.getGeoConcepts(self.triplestoreconf[endpointIndex]["resource"],
                                    self.triplestoreconf[endpointIndex]["geoconceptquery"], "class", None,
                                    True, self.triplestoreconf[endpointIndex]["examplequery"])
            elif "geoconceptquery" in self.triplestoreconf[endpointIndex]:
                self.getGeoConcepts(self.triplestoreconf[endpointIndex]["resource"],
                                    self.triplestoreconf[endpointIndex]["geoconceptquery"], "class", None,
                                    True, None)
        elif "staticconcepts" in self.triplestoreconf[endpointIndex] and self.triplestoreconf[endpointIndex][
            "staticconcepts"] != []:
            conceptlist = self.triplestoreconf[endpointIndex]["staticconcepts"]
            self.autocomplete["completerClassList"] = {}
            self.conceptViewTabWidget.setTabText(0, "GeoConcepts (" + str(len(conceptlist)) + ")")
            for concept in conceptlist:
                item = QStandardItem()
                item.setData(concept, 256)
                item.setText(SPARQLUtils.labelFromURI(concept, self.triplestoreconf[endpointIndex]["prefixesrev"]))
                item.setIcon(UIUtils.geoclassicon)
                item.setData(SPARQLUtils.geoclassnode, 257)
                self.autocomplete["completerClassList"][SPARQLUtils.labelFromURI(concept)] = "<" + concept + ">"
                self.geoTreeViewModel.appendRow(item)
            self.inp_sparql2.updateNewClassList()
            if len(conceptlist) > 0:
                self.geoTreeView.selectionModel().setCurrentIndex(self.geoTreeView.model().index(0, 0),QItemSelectionModel.SelectCurrent)
            if "examplequery" in self.triplestoreconf[endpointIndex]:
                self.inp_sparql2.setPlainText(self.triplestoreconf[endpointIndex]["examplequery"])
                self.inp_sparql2.columnvars = {}
        if (isinstance(self.triplestoreconf[endpointIndex]["resource"]["url"], str) and "wikidata" not in
            self.triplestoreconf[endpointIndex]["resource"]["url"]) or (not isinstance(
            self.triplestoreconf[endpointIndex]["resource"]["url"], str) and "instance" in self.triplestoreconf[endpointIndex]["resource"]):
            self.getClassTree()
        if "geocollectionquery" in self.triplestoreconf[endpointIndex]:
            query = str(self.triplestoreconf[endpointIndex]["geocollectionquery"])
            #QgsMessageLog.logMessage('Started task "{}"'.format(str(query)), "SPARQL Unicorn", Qgis.Info)
            if "featurecollectionclasses" in self.triplestoreconf[endpointIndex] and \
                    self.triplestoreconf[endpointIndex]["featurecollectionclasses"] != None and \
                    self.triplestoreconf[endpointIndex]["featurecollectionclasses"] != "" and \
                    self.triplestoreconf[endpointIndex]["featurecollectionclasses"] != []:
                valstatement = " VALUES ?collclass { "
                for featclass in self.triplestoreconf[endpointIndex]["featurecollectionclasses"]:
                    valstatement += "<" + str(featclass) + "> "
                valstatement += "} "
                querymod = query.replace("%%concept%% .", "?collclass . " + str(valstatement))
            else:
                rep = "<http://www.opengis.net/ont/geosparql#FeatureCollection>"
                querymod = str(self.triplestoreconf[endpointIndex]["geocollectionquery"]).replace("%%concept%% .", rep)
            #QgsMessageLog.logMessage('Started task "{}"'.format(str(query)), "SPARQL Unicorn", Qgis.Info)
            self.getGeoCollectionInstances(self.triplestoreconf[endpointIndex]["resource"],
                                           querymod, "colinstance", None,
                                           True, None)
            query = str(self.triplestoreconf[endpointIndex]["geocollectionquery"])
            if "geometrycollectionclasses" in self.triplestoreconf[endpointIndex] and \
                    self.triplestoreconf[endpointIndex]["geometrycollectionclasses"] != None and \
                    self.triplestoreconf[endpointIndex]["geometrycollectionclasses"] != "" and \
                    self.triplestoreconf[endpointIndex]["geometrycollectionclasses"] != []:
                valstatement = " VALUES ?collclass { "
                for geoclass in self.triplestoreconf[endpointIndex]["geometrycollectionclasses"]:
                    valstatement += "<" + str(geoclass) + "> "
                valstatement += "} "
                querymod = query.replace("%%concept%% .", "?collclass . " + str(valstatement))
            else:
                rep = "<http://www.opengis.net/ont/geosparql#GeometryCollection>"
                querymod = str(self.triplestoreconf[endpointIndex]["geocollectionquery"]).replace("%%concept%% .", rep)
            #QgsMessageLog.logMessage('Started task "{}"'.format(str(query)), "SPARQL Unicorn", Qgis.Info)
            self.getGeoCollectionInstances(self.triplestoreconf[endpointIndex]["resource"],
                                           querymod, "colinstance", None,
                                           False, None)
        """
        if "areaconcepts" in self.triplestoreconf[endpointIndex] and self.triplestoreconf[endpointIndex][
            "areaconcepts"]:
            conceptlist2 = self.triplestoreconf[endpointIndex]["areaconcepts"]
            for concept in conceptlist2:
                selfareaconcepts.addItem(concept["concept"])
        """
        if "querytemplate" in self.triplestoreconf[endpointIndex]:
            for concept in self.triplestoreconf[endpointIndex]["querytemplate"]:
                self.queryTemplates.addItem(concept["label"],concept["query"])
        if "resource" in self.triplestoreconf[endpointIndex] and "url" in self.triplestoreconf[endpointIndex]["resource"] and isinstance(self.triplestoreconf[endpointIndex]["resource"]["url"],str) and self.triplestoreconf[endpointIndex]["resource"]["url"] in self.savedQueriesJSON:
            self.savedQueries.clear()
            for concept in self.savedQueriesJSON[self.triplestoreconf[endpointIndex]["resource"]["url"]]:
                self.savedQueries.addItem(concept["label"],concept["query"])



    def onContext4(self, position):
        self.currentContext = self.classTreeView
        self.currentContextModel = self.classTreeViewModel
        self.currentProxyModel = self.classTreeViewProxyModel
        self.createMenu(position)

    def createLayerFromTreeEntry(self):
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        nodetype = self.currentContextModel.itemFromIndex(curindex).data(257)
        if nodetype==SPARQLUtils.geoclassnode or nodetype==SPARQLUtils.classnode:
            self.dataAllInstancesAsLayer()
        elif nodetype==SPARQLUtils.geoinstancenode or nodetype==SPARQLUtils.instancenode:
            self.dataInstanceAsLayer()
        elif nodetype==SPARQLUtils.collectionclassnode:
            self.dataAllInstancesAsLayer()

    def tabchanged(self,index):
        #QgsMessageLog.logMessage('Started task "{}"'.format("Tab changed! "+str(index)), MESSAGE_CATEGORY, Qgis.Info)
        if self.currentProxyModel!=None:
            self.currentProxyModel.setFilterRegExp("")
        self.filterConcepts.setText("")
        if index==0:
            self.currentProxyModel=self.geoTreeViewProxyModel
            self.currentContext = self.geoTreeView
            self.currentContextModel = self.geoTreeViewModel
        elif index==1:
            self.currentProxyModel=self.featureCollectionProxyModel
            self.currentContext = self.featureCollectionClassList
            self.currentContextModel = self.featureCollectionClassListModel
        elif index==2:
            self.currentProxyModel=self.geometryCollectionProxyModel
            self.currentContext = self.geometryCollectionClassList
            self.currentContextModel = self.geometryCollectionClassListModel
        elif index==3:
            self.currentProxyModel=self.classTreeViewProxyModel
            self.currentContext = self.classTreeView
            self.currentContextModel = self.classTreeViewModel

    def buildUploadRDFDialog(self):
        print("todo")
        #uploaddialog = UploadRDFDialog(ttlstring, self.triplestoreconf)
        #uploaddialog.setMinimumSize(450, 250)
        #uploaddialog.setWindowTitle("Upload interlinked dataset to triple store ")
        #uploaddialog.exec_()

    def collectionSelectAction(self):
        endpointIndex = self.comboBox.currentIndex()
        if endpointIndex == 0:
            self.justloadingfromfile = False
            return
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        if self.currentContext.selectionModel().currentIndex() is not None and self.currentContextModel.itemFromIndex(
                curindex) is not None:
            concept = self.currentContextModel.itemFromIndex(curindex).data(256)
            querytext = self.triplestoreconf[endpointIndex]["querytemplate"][self.queryTemplates.currentIndex()][
            "query"].replace("?item a <%%concept%%>", "<"+concept+"> rdfs:member ?item ")
            self.inp_sparql2.setPlainText(querytext)
            self.inp_sparql2.columnvars = {}

    def conceptSelectAction(self):
        concept = ""
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        if self.currentContext.selectionModel().currentIndex() is not None and self.currentContextModel.itemFromIndex(
                curindex) is not None and re.match(r'.*Q[0-9]+.*', self.currentContextModel.itemFromIndex(
            curindex).text()) and not self.currentContextModel.itemFromIndex(curindex).text().startswith("http"):
            self.inp_label.setText(
                self.currentContextModel.itemFromIndex(curindex).text().split("(")[0].lower().replace(" ", "_"))
            concept = "Q" + self.currentContextModel.itemFromIndex(curindex).text().split("Q")[1].replace(")", "")
        elif self.currentContextModel.itemFromIndex(curindex) is not None:
            concept = self.currentContextModel.itemFromIndex(curindex).data(256)
        if self.queryTemplates.count()>0:
            if "wd:Q%%concept%% ." in self.queryTemplates.itemData(self.queryTemplates.currentIndex()):
                querytext = ""
                if concept != None and concept.startswith("http"):
                    querytext = \
                        self.queryTemplates.itemData(self.queryTemplates.currentIndex()).replace("wd:Q%%concept%% .", "wd:" + concept[concept.rfind('/') + 1:] + " .")
                elif concept != None:
                    querytext = \
                        self.queryTemplates.itemData(self.queryTemplates.currentIndex()).replace("wd:Q%%concept%% .", "wd:" + concept + " .")
            else:
                querytext = self.queryTemplates.itemData(self.queryTemplates.currentIndex()).replace("%%concept%%", concept)
            self.inp_sparql2.setPlainText(querytext)
            self.inp_sparql2.columnvars = {}
        if self.currentContext.selectionModel().currentIndex() is not None and self.currentContextModel.itemFromIndex(
                curindex) is not None and "#" in self.currentContextModel.itemFromIndex(curindex).text():
            self.inp_label.setText(self.currentContextModel.itemFromIndex(curindex).text()[
                                   self.currentContextModel.itemFromIndex(curindex).text().rfind(
                                       '#') + 1:].lower().replace(" ", "_"))
        elif self.currentContext.selectionModel().currentIndex() is not None and self.currentContextModel.itemFromIndex(
                curindex) is not None:
            self.inp_label.setText(self.currentContextModel.itemFromIndex(curindex).text()[
                                   self.currentContextModel.itemFromIndex(curindex).text().rfind(
                                       '/') + 1:].lower().replace(" ", "_"))

    ## Validates the SPARQL query in the input field and outputs errors in a label.
    #  @param self The object pointer.
    def validateSPARQL(self):
        if self.inp_sparql2.toPlainText() is not None and self.inp_sparql2.toPlainText() != "":
            try:
                if self.prefixes is not None and len(self.prefixes)>self.comboBox.currentIndex() and self.prefixes[self.comboBox.currentIndex()] != None and self.prefixes[self.comboBox.currentIndex()] != "":
                    prepareQuery(
                        "".join(self.prefixes[self.comboBox.currentIndex()]) + "\n" + self.inp_sparql2.toPlainText())
                else:
                    prepareQuery(self.inp_sparql2.toPlainText())
                self.errorLabel.setText("Valid Query")
                self.errorline = -1
                self.sparqlhighlight.errorhighlightline = self.errorline
                self.sparqlhighlight.currentline = 0
                self.inp_sparql2.errorline = None
            except Exception as e:
                match = re.search(r'line:([0-9]+),', str(e))
                start=-1
                if self.prefixes is not None and len(self.prefixes)>self.comboBox.currentIndex() and self.prefixes[
                    self.comboBox.currentIndex()] != None and self.prefixes[self.comboBox.currentIndex()] != "" and match!=None:
                    start = int(match.group(1)) - len(self.triplestoreconf[self.comboBox.currentIndex()]["prefixes"]) - 1
                elif match!=None:
                    start = int(match.group(1)) - 1
                if "line" in str(e):
                    self.errorLabel.setText(re.sub("line:([0-9]+),", "line: " + str(start) + ",", str(e)))
                    self.inp_sparql2.errorline = start - 1
                    ex = str(e)
                    start = ex.find('line:') + 5
                    end = ex.find(',', start)
                    start2 = ex.find('col:') + 4
                    end2 = ex.find(')', start2)
                    self.errorline = ex[start:end]
                    self.sparqlhighlight.errorhighlightcol = ex[start2:end2]
                    self.sparqlhighlight.errorhighlightline = self.errorline
                    self.sparqlhighlight.currentline = 0
                else:
                    self.errorLabel.setText(str(e))

    ##
    #  @brief Builds the search dialog to search for a concept or class.
    #  @param  self The object pointer
    #  @param  row the row to insert the result
    #  @param  column the column to insert the result
    #  @param  interlinkOrEnrich indicates if the dialog is meant for interlinking or enrichment
    #  @param  table the GUI element to display the result
    def buildSearchDialog(self, row=-1, column=-1, interlinkOrEnrich=False, table=None, propOrClass=1, bothOptions=False,
                          currentprefixes=None, addVocabConf=None):
        self.currentcol = column
        self.currentrow = row
        self.interlinkdialog = SearchDialog(column, row, self.triplestoreconf, self.prefixes, interlinkOrEnrich, table,
                                            propOrClass, bothOptions, currentprefixes, addVocabConf)
        self.interlinkdialog.setMinimumSize(650, 400)
        self.interlinkdialog.setWindowTitle("Search Interlink Concept")
        self.interlinkdialog.exec_()

    ##
    #  @brief Builds a value mapping dialog window for ther interlinking dialog.
    #
    #  @param self The object pointer
    #  @param row The row of the table for which to map the value
    #  @param column The column of the table for which to map the value
    #  @param table The table in which to save the value mapping result
    #  @param layer The layer which is concerned by the enrichment oder interlinking
    def buildValueMappingDialog(self, row, column, interlinkOrEnrich, table, layer):
        self.currentcol = column
        self.currentrow = row
        valuemap = None
        if table.item(row, column) != None and table.item(row, column).text() != "":
            valuemap = table.item(row, column).data(1)
        self.interlinkdialog = ValueMappingDialog(column, row, self.triplestoreconf, interlinkOrEnrich, table,
                                                  table.item(row, 3).text(), layer, valuemap)
        self.interlinkdialog.setMinimumSize(650, 400)
        self.interlinkdialog.setWindowTitle("Get Value Mappings for column " + table.item(row, 3).text())
        self.interlinkdialog.exec_()

    def dataInstanceAsLayer(self):
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        concept = self.currentContextModel.itemFromIndex(curindex).data(256)
        nodetype = self.currentContextModel.itemFromIndex(curindex).data(257)
        if nodetype==SPARQLUtils.geoinstancenode:
            if "geotriplepattern" in self.triplestoreconf[self.comboBox.currentIndex()]:
                self.qlayerinstance = QueryLayerTask(
                    "Instance to Layer: " + str(concept),
                    concept,
                    self.triplestoreconf[self.comboBox.currentIndex()]["resource"],
                    "SELECT ?"+" ?".join(self.triplestoreconf[self.comboBox.currentIndex()]["mandatoryvariables"])+" ?rel ?val\n WHERE\n {\n BIND( <" + str(concept) + "> AS ?item)\n ?item ?rel ?val . " +
                    self.triplestoreconf[self.comboBox.currentIndex()]["geotriplepattern"][0] + "\n }",
                    self.triplestoreconf[self.comboBox.currentIndex()], False, SPARQLUtils.labelFromURI(concept), None)
            else:
                self.qlayerinstance = QueryLayerTask(
                "Instance to Layer: " + str(concept),
                    concept,
                self.triplestoreconf[self.comboBox.currentIndex()]["resource"],
                "SELECT ?item ?rel ?val \n WHERE\n {\n BIND( <"+str(concept)+"> AS ?item)\n ?item ?rel ?val . \n }",
                self.triplestoreconf[self.comboBox.currentIndex()],True, SPARQLUtils.labelFromURI(concept),None)
        else:
            self.qlayerinstance = QueryLayerTask(
                "Instance to Layer: " + str(concept),
                concept,
                self.triplestoreconf[self.comboBox.currentIndex()]["resource"],
                "SELECT ?item ?rel ?val\n WHERE\n {\n BIND( <"+str(concept)+"> AS ?item)\n ?item ?rel ?val .\n }",
                self.triplestoreconf[self.comboBox.currentIndex()],True, SPARQLUtils.labelFromURI(concept),None)
        QgsApplication.taskManager().addTask(self.qlayerinstance)

    def subclassQuerySelectAction(self):
        endpointIndex = self.comboBox.currentIndex()
        if endpointIndex == 0:
            self.justloadingfromfile = False
            return
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        if self.currentContext.selectionModel().currentIndex() is not None and self.item is not None:
            concept = self.item.data(256)
            querytext = self.triplestoreconf["querytemplate"][self.queryTemplates.currentIndex()][
            "query"].replace("?item a <%%concept%%>", "?item a ?con . ?con rdfs:subClassOf* <"+concept+"> ")
            self.inp_sparql2.setPlainText(querytext)
            self.inp_sparql2.columnvars = {}

    def dataAllInstancesAsLayer(self):
        curindex = self.currentProxyModel.mapToSource(self.currentContext.selectionModel().currentIndex())
        concept = self.currentContextModel.itemFromIndex(curindex).data(256)
        nodetype = self.currentContextModel.itemFromIndex(curindex).data(257)
        progress = QProgressDialog(
            "Querying all instances for " + concept,"Abort", 0, 0, self)
        progress.setWindowTitle("Query all instances")
        progress.setWindowModality(Qt.WindowModal)
        if nodetype==SPARQLUtils.geoclassnode:
            if "geotriplepattern" in self.triplestoreconf[self.comboBox.currentIndex()]:
                self.qlayerinstance = QueryLayerTask(
                "All Instances to Layer: " + str(concept),
                    concept,
                    self.triplestoreconf[self.comboBox.currentIndex()]["resource"],
                "SELECT ?"+" ?".join(self.triplestoreconf[self.comboBox.currentIndex()]["mandatoryvariables"])+" ?rel ?val\n WHERE\n {\n ?item <"+str(self.triplestoreconf[self.comboBox.currentIndex()]["typeproperty"])+"> <"+str(concept)+"> . ?item ?rel ?val . "+self.triplestoreconf[self.comboBox.currentIndex()]["geotriplepattern"][0]+"\n } ORDER BY ?item",
                self.triplestoreconf[self.comboBox.currentIndex()],True, SPARQLUtils.labelFromURI(concept),progress)
            else:
                self.qlayerinstance = QueryLayerTask(
                "All Instances to Layer: " + str(concept),
                    concept,
                    self.triplestoreconf[self.comboBox.currentIndex()]["resource"],
                "SELECT ?item ?rel ?val\n WHERE\n {\n ?item <"+str(self.triplestoreconf[self.comboBox.currentIndex()]["typeproperty"])+"> <"+str(concept)+"> .\n ?item ?rel ?val .\n } ORDER BY ?item",
                self.triplestoreconf[self.comboBox.currentIndex()],True, SPARQLUtils.labelFromURI(concept),progress)
        elif nodetype == SPARQLUtils.collectionclassnode:
            if "geotriplepattern" in self.triplestoreconf[self.comboBox.currentIndex()]:
                self.qlayerinstance = QueryLayerTask(
                "All Instances to Layer: " + str(concept),
                    concept,
                    self.triplestoreconf[self.comboBox.currentIndex()]["resource"],
                "SELECT ?"+" ?".join(self.triplestoreconf[self.comboBox.currentIndex()]["mandatoryvariables"])+" ?rel ?val\n WHERE\n {\n <"+str(concept)+"> <http://www.w3.org/2000/01/rdf-schema#member> ?item . ?item ?rel ?val . "+self.triplestoreconf[self.comboBox.currentIndex()]["geotriplepattern"][0]+"\n } ORDER BY ?item",
                self.triplestoreconf[self.comboBox.currentIndex()],True, SPARQLUtils.labelFromURI(concept),progress)
            else:
                self.qlayerinstance = QueryLayerTask(
                "All Instances to Layer: " + str(concept),
                    concept,
                    self.triplestoreconf[self.comboBox.currentIndex()]["resource"],
                "SELECT ?item ?rel ?val\n WHERE\n {\n <"+str(concept)+"> <http://www.w3.org/2000/01/rdf-schema#member> ?item .\n ?item ?rel ?val .\n } ORDER BY ?item",
                self.triplestoreconf[self.comboBox.currentIndex()],True, SPARQLUtils.labelFromURI(concept),progress)
        else:
            self.qlayerinstance = QueryLayerTask(
                "All Instances to Layer: " + str(concept),
                concept,
                self.triplestoreconf[self.comboBox.currentIndex()]["resource"],
                "SELECT ?item ?rel ?val\n WHERE\n {\n ?item <"+str(self.triplestoreconf[self.comboBox.currentIndex()]["typeproperty"])+"> <"+str(concept)+"> . ?item ?rel ?val .\n } ORDER BY ?item",
                self.triplestoreconf[self.comboBox.currentIndex()],True, SPARQLUtils.labelFromURI(concept),progress)
        QgsApplication.taskManager().addTask(self.qlayerinstance)