# -*- coding: utf-8 -*-
"""
/***************************************************************************
 SPAQLunicorn
                                 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
        developer(s)         : Florian Thiery,  Timo Homburg
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 sys
#import pip
from qgis.utils import iface
from qgis.core import Qgis

from qgis.PyQt.QtCore import QSettings, QTranslator, QThread,QCoreApplication,QObject,QRegExp, Qt,pyqtSignal
from qgis.PyQt.QtGui import QColor, QTextCharFormat, QFont, QIcon, QSyntaxHighlighter,QTextCursor,QIntValidator,QRegExpValidator,QValidator
from qgis.PyQt.QtWidgets import QAction, QFileDialog, QTableWidgetItem,QListWidgetItem, QCheckBox, QDialog, QPushButton,QPlainTextEdit,QTextEdit, QLabel, QLineEdit,QCompleter, QListWidget, QComboBox, QRadioButton,QMessageBox, QHBoxLayout,QWidget, QToolTip
from qgis.core import QgsProject, Qgis,QgsRasterLayer,QgsPointXY, QgsRectangle, QgsDistanceArea
from qgis.core import QgsVectorLayer, QgsProject, QgsGeometry,QgsFeature, QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsWkbTypes,QgsMapLayer
from qgis.gui import QgsMapToolEmitPoint, QgsMapCanvas, QgsRubberBand,QgsMapTool
from qgis.utils import iface
import rdflib
from rdflib.plugins.sparql import prepareQuery
import sys
import requests
import uuid

# Initialize Qt resources from file resources.py
from .resources import *
# Import the code for the dialog
from .sparql_unicorn_dialog import SPAQLunicornDialog
import os.path
import re

# external libraires for SPARQL Unicorn
from SPARQLWrapper import SPARQLWrapper, JSON
#import rdflib
import json
#from convertbng.util import convert_bng, convert_lonlat


def format(color, style=''):
    """Return a QTextCharFormat with the given attributes.
    """
    _color = QColor()
    _color.setNamedColor(color)

    _format = QTextCharFormat()
    _format.setForeground(_color)
    if 'bold' in style:
        _format.setFontWeight(QFont.Bold)
    if 'italic' in style:
        _format.setFontItalic(True)
 
    return _format

STYLES = {
    'keyword': format('#b32424'),
    'operator': format('black'),
    'error': format('red'),
    'brace': format('black'),
    'defclass': format('#14866d'),
    'uri': format('#2a4b8d'),
	'prefixcls': format('#14866d'),
    'string': format('#ac6600'),
    'string2': format('darkMagenta'),
    'comment': format('#72777d'),
    'self': format('blue', 'italic'),
    'numbers': format('black'),
}

class RectangleMapTool(QgsMapToolEmitPoint):

    rectangleCreated = pyqtSignal()
    deactivated = pyqtSignal()
	
    point1=""
    point2=""
    point3=""
    point4=""
    chosen=False

    def __init__(self, canvas):
        self.canvas = canvas
        QgsMapToolEmitPoint.__init__(self, self.canvas)

        self.rubberBand = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry)
        self.rubberBand.setColor(QColor(255, 0, 0, 100))
        self.rubberBand.setWidth(2)

        self.reset()

    def reset(self):
        self.startPoint = self.endPoint = None
        self.isEmittingPoint = False
        self.rubberBand.reset(QgsWkbTypes.PolygonGeometry)

    def canvasPressEvent(self, e):
        self.startPoint = self.toMapCoordinates(e.pos())
        self.endPoint = self.startPoint
        self.isEmittingPoint = True

        self.showRect(self.startPoint, self.endPoint)

    def canvasReleaseEvent(self, e):
        self.isEmittingPoint = False
        if self.rectangle() is not None:
            self.rectangleCreated.emit()

    def canvasMoveEvent(self, e):
        if not self.isEmittingPoint:
            return

        self.endPoint = self.toMapCoordinates(e.pos())
        self.showRect(self.startPoint, self.endPoint)

    def showRect(self, startPoint, endPoint):
        self.rubberBand.reset(QgsWkbTypes.PolygonGeometry)
        if startPoint.x() == endPoint.x() or startPoint.y() == endPoint.y():
            return

        self.point1 = QgsPointXY(startPoint.x(), startPoint.y())
        self.point2 = QgsPointXY(startPoint.x(), endPoint.y())
        self.point3 = QgsPointXY(endPoint.x(), endPoint.y())
        self.point4 = QgsPointXY(endPoint.x(), startPoint.y())

        self.rubberBand.addPoint(self.point1, False)
        self.rubberBand.addPoint(self.point2, False)
        self.rubberBand.addPoint(self.point3, False)
        # True to update canvas
        self.rubberBand.addPoint(self.point4, True)
        self.rubberBand.show()
        chosen=True

    def rectangle(self):
        if self.startPoint is None or self.endPoint is None:
            return None
        elif self.startPoint.x() == self.endPoint.x() or \
                self.startPoint.y() == self.endPoint.y():
            return None

        return QgsRectangle(self.startPoint, self.endPoint)

    def setRectangle(self, rect):
        if rect == self.rectangle():
            return False

        if rect is None:
            self.reset()
        else:
            self.startPoint = QgsPointXY(rect.xMaximum(), rect.yMaximum())
            self.endPoint = QgsPointXY(rect.xMinimum(), rect.yMinimum())
            self.showRect(self.startPoint, self.endPoint)
        return True

    def deactivate(self):
        QgsMapTool.deactivate(self)
        self.deactivated.emit()

class SPARQLHighlighter (QSyntaxHighlighter):
    """Syntax highlighter for the Python language.
    """
    # Python keywords
    keywords = [
        'SELECT', 'INSERT', 'WHERE', 'ORDER', 'BY', 'LIMIT',
        'OFFSET', 'FROM', 'PREFIX', 'GRAPH', 'NAMED', 'BIND',
        'VALUES', 'ASC', 'DESC', 'FILTER', 'DISTINCT', 'REDUCED',
        'OPTIONAL', 'CONSTRUCT', 'ASK', 'DESCRIBE', 'BOUND', 'IF','SERVICE',
        'EXISTS', 'NOT', 'IN', 'STR', 'AS','LANG','DELETE','CREATE','CLEAR','DROP','LOAD','COPY','MOVE','ADD'
        'IRI', 'URI', 'False', 'a'
    ]
  
    # Python operators
    operators = [
        '=',
        # Comparison
        '==', '!=', '<', '<=', '>', '>=',
        # Arithmetic
        '\+', '-', '\*', '/', '//', '\%', '\*\*',
        # In-place
        '\+=', '-=', '\*=', '/=', '\%=',
        # Bitwise
        '\^', '\|', '\&', '\~', '>>', '<<',
    ]
	
    errorhighlightline=-1

    currentline=0

    errorhighlightcol=-1
  
    # Python braces
    braces = [
        '\{', '\}', '\(', '\)', '\[', '\]',
    ]
    def __init__(self, document,errorlabel):
        QSyntaxHighlighter.__init__(self, document.document())
        #msgBox=QMessageBox()
        #msgBox.setText(document.toPlainText())
        #msgBox.exec()
        # Multi-line strings (expression, flag, style)
        # FIXME: The triple-quotes in these two lines will mess up the
        # syntax highlighting from this point onward
        self.tri_single = (QRegExp("'''"), 1, STYLES['string2'])
        self.tri_double = (QRegExp('"""'), 2, STYLES['string2'])
  
        rules = []
  
  
          # All other rules
        rules += [
            # 'self'
            (r'\bself\b', 0, STYLES['self']),
  
            # Double-quoted string, possibly containing escape sequences
            (r'"[^"\\]*(\\.[^"\\]*)*"', 0, STYLES['string']),
            # Single-quoted string, possibly containing escape sequences
            (r"'[^'\\]*(\\.[^'\\]*)*'", 0, STYLES['string']),
  
            # 'def' followed by an identifier
            (r'([?]\w+)', 1, STYLES['defclass']),
            (r'([<][h][t][t][p][:][/][/]\w+[>])', 0, STYLES['uri']),
			# 'class' followed by an identifier
            (r'(\w+[:]\w+)', 1, STYLES['uri']),
			
  
            # From '#' until a newline
            (r'#[^\n]*', 0, STYLES['comment']),
  
            # Numeric literals
            (r'\b[+-]?[0-9]+[lL]?\b', 0, STYLES['numbers']),
            (r'\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b', 0, STYLES['numbers']),
            (r'\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b', 0, STYLES['numbers']),
        ]
		        # Keyword, operator, and brace rules
        rules += [(r'\b%s\b' % w, 0, STYLES['keyword'])
            for w in SPARQLHighlighter.keywords]
        rules += [(r'%s' % o, 0, STYLES['operator'])
            for o in SPARQLHighlighter.operators]
        rules += [(r'%s' % b, 0, STYLES['brace'])
            for b in SPARQLHighlighter.braces]
  
        # Build a QRegExp for each pattern
        self.rules = [(QRegExp(pat), index, fmt)
            for (pat, index, fmt) in rules]
  
  
    def highlightBlock(self, text):
        """Apply syntax highlighting to the given block of text.
        """
        self.currentline+=1
        #msgBox=QMessageBox()
        #msgBox.setText(str(self.errorhighlightline))
        #msgBox.exec()
        #if self.errorhighlightline!=-1:
        #    self.setFormat(0, len(text), STYLES['error'])
        #else:
		#    # Do other syntax formatting
        for expression, nth, format in self.rules:
            index = expression.indexIn(text, 0)
            while index >= 0:
                # We actually want the index of the nth match
                index = expression.pos(nth)
                length = expression.matchedLength()
                self.setFormat(index, length, format)
                index = expression.indexIn(text, index + length)
  
        self.setCurrentBlockState(0)
        # Do multi-line strings
        in_multiline = self.match_multiline(text, *self.tri_single)
        if not in_multiline:
            in_multiline = self.match_multiline(text, *self.tri_double)
  
  
    def match_multiline(self, text, delimiter, in_state, style):
        """Do highlighting of multi-line strings. ``delimiter`` should be a
        ``QRegExp`` for triple-single-quotes or triple-double-quotes, and
        ``in_state`` should be a unique integer to represent the corresponding
        state changes when inside those strings. Returns True if we're still
        inside a multi-line string when this function is finished.
        """
        # If inside triple-single quotes, start at 0
        if self.previousBlockState() == in_state:
            start = 0
            add = 0
        # Otherwise, look for the delimiter on this line
        else:
            start = delimiter.indexIn(text)
            # Move past this match
            add = delimiter.matchedLength()
  
        # As long as there's a delimiter match on this line...
        while start >= 0:
            # Look for the ending delimiter
            end = delimiter.indexIn(text, start + add)
            # Ending delimiter on this line?
            if end >= add:
                length = end - start + add + delimiter.matchedLength()
                self.setCurrentBlockState(0)
            # No; multi-line string
            else:
                self.setCurrentBlockState(in_state)
                length = text.length() - start + add
            # Apply formatting
            self.setFormat(start, length, style)
            # Look for the next match
            start = delimiter.indexIn(text, start + length)
  
        # Return True if still inside a multi-line string, False otherwise
        if self.currentBlockState() == in_state:
            return True
        else:
            return False

geoconcepts=""


class GeoConceptsThread(QThread):
    signal = pyqtSignal('PyQt_PyObject')

    query=""
    
    triplestoreurl=""
   
    graph=None

    def __init__(self,query,url,graph):
        QThread.__init__(self)
        #self.git_url = ""
        self.query=query
        self.triplestoreurl=url
        self.graph=graph

    # run method gets called when we start the thread
    def run(self):
        print("THREADSTART")
        viewlist=[]
        print(self.query)
        print(self.triplestoreurl)
        print(self.graph)
        if self.graph!=None:
            print("WE HAVE A GRAPH")
            results = self.graph.query(self.query)
            for row in results:
                viewlist.append(str(row[0]))
        else:
            sparql = SPARQLWrapper(self.triplestoreurl, agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11")
            sparql.setQuery(self.query)
            print("now sending query")
            sparql.setReturnFormat(JSON)
            results = sparql.query().convert()
            for result in results["results"]["bindings"]:
                viewlist.append(str(result[queryvar]["value"]))
        print(viewlist)	
        #geoconcepts=viewlist
        #self.signal.emit(tmpdir)
        # git clone done, now inform the main thread with the output


class GeoConceptsWorker(QObject):
    finished = pyqtSignal()
    intReady = pyqtSignal(int)

    query=""
    
    triplestoreurl=""
   
    graph=None
    
    signalStatus = QtCore.pyqtSignal(str)

    def __init__(self,query,url,graph,parent=None):
        super(self.__class__, self).__init__(parent)
        self.query=query
        self.triplestoreurl=url
        self.graph=graph
    
    @QtCore.pyqtSlot()
    def startWork(self):
        print("THREADSTART")
        viewlist=[]
        print(self.query)
        print(self.triplestoreurl)
        print(self.graph)
        if self.graph!=None:
            print("WE HAVE A GRAPH")
            results = self.graph.query(self.query)
            for row in results:
                viewlist.append(str(row[0]))
        else:
            sparql = SPARQLWrapper(self.triplestoreurl, agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11")
            sparql.setQuery(self.query)
            print("now sending query")
            sparql.setReturnFormat(JSON)
            results = sparql.query().convert()
            for result in results["results"]["bindings"]:
                viewlist.append(str(result[queryvar]["value"]))
        print(viewlist)	
        geoconcepts=viewlist
        self.finished.emit()


class ToolTipPlainText(QPlainTextEdit):      

    def __init__(self,parent=None):
        super(self.__class__, self).__init__(parent)
        self.setMouseTracking(True)
        
    def mouseMoveEvent(self, event):
        textCursor = self.cursorForPosition(event.pos())
        textCursor.select(QTextCursor.WordUnderCursor)
        word = textCursor.selectedText()
        #
            #msgBox=QMessageBox()
            #msgBox.setText(word)
            #msgBox.exec()
            
        #while not word.endswith(" "):
        #    self.setPosition(self.anchor()+1,QtGui.QTextCursor.KeepAnchor)
        #    word = textCursor.selectedText()        
        #if not word.startswith(" "):
            
        if True: #"http" in word:
            #if not word.endswith(' '):
                #self.moveCursor(QTextCursor.NextCharacter,QTextCursor.KeepAnchor)
                #word = textCursor.selectedText()
            toolTipText = word
            # Put the hover over in an easy to read spot
            pos = self.cursorRect(self.textCursor()).bottomRight()
            # The pos could also be set to event.pos() if you want it directly under the mouse
            pos = self.mapToGlobal(pos)
            QToolTip.showText(event.screenPos().toPoint(), word)
        #textCursor.clearSelection()
        #self.setTextCursor(self.textCursor())

class SPAQLunicorn:
    """QGIS Plugin Implementation."""

    loadedfromfile=False
    
    currentquery=""
	
    justloadingfromfile=False
	
    tableCheckBoxes=[]

    currentgraph=None
	
    currentcol=-1
	
    epsgEdit=-1
	
    interlinkOrEnrich=True
	
    triplestoreconf=None
    
    tripleStoreChooser=None
    
    vl=""

    bboxbuffer=""

    currentrow=-1

    exportNameSpace=""
	
    bboxextent=""
	
    rect_tool=""
	
    curbbox=[]
	
    bboxCoordinateLabelLon=""

    bboxCoordinateLabelLat=""

    exportIdCol=""
	
    mts_layer=""
	
    map_canvas=""
	
    exportClassCol=""

    exportSetClass=""
    
    exampleQuery=""

    activeCheckBox=""

    searchResult=""

    tripleStoreEdit=""
    
    addTripleStore=False

    conceptSearchEdit=""
	
    sparqlhighlight=""
	
    interlinkdialog=""

    exportColConfig={}
	
    errorline=-1
    
    layerExtentOrBBOX=False

    chooseBBOXLayer=""
	 
    d=""

    enrichedExport=False

    outputfile=""
	
    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(
            self.plugin_dir,
            'i18n',
            'SPAQLunicorn_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)
            QCoreApplication.installTranslator(self.translator)

        # Declare instance attributes
        self.actions = []
        self.menu = self.tr(u'&SPARQL Unicorn Wikidata Plugin')

        # Check if plugin was started the first time in current QGIS session
        # Must be set in initGui() to survive plugin reloads
        self.first_start = None

    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate('SPAQLunicorn', message)


    def validateSPARQL(self):
        try:
            prepareQuery("".join(self.triplestoreconf[self.dlg.comboBox.currentIndex()]["prefixes"])+"\n"+self.dlg.inp_sparql.toPlainText())
            self.dlg.errorLabel.setText("Valid Query")
            self.errorline=-1
            self.sparqlhighlight.errorhighlightline=self.errorline
            self.sparqlhighlight.currentline=0
        except Exception as e:
            self.dlg.errorLabel.setText(str(e))
            if "line" in str(e):
                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
                #msgBox=QMessageBox()
                #msgBox.setText(str(self.errorline)+" "+str(self.sparqlhighlight.errorhighlightline)+" "+str(self.sparqlhighlight.errorhighlightcol))
                #msgBox.exec()

    def add_action(
        self,
        icon_path,
        text,
        callback,
        enabled_flag=True,
        add_to_menu=True,
        add_to_toolbar=True,
        status_tip=None,
        whats_this=None,
        parent=None):
        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            # Adds plugin icon to Plugins toolbar
            self.iface.addToolBarIcon(action)

        if add_to_menu:
            self.iface.addPluginToVectorMenu(
                self.menu,
                action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""
        #a = str('numpy' in sys.modules)
        #iface.messageBar().pushMessage("load libs", a, level=Qgis.Success)

        icon_path = ':/plugins/sparql_unicorn/icon.png'
        self.add_action(
            icon_path,
            text=self.tr(u'Adds GeoJSON layer from a Wikidata'),
            callback=self.run,
            parent=self.iface.mainWindow())

        # will be set False in run()
        self.first_start = True


    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iface.removePluginVectorMenu(
                self.tr(u'&SPARQL Unicorn Wikidata Plugin'),
                action)
            self.iface.removeToolBarIcon(action)

    def processResults(self,results,reproject,mandatoryvars):
        latval=mandatoryvars[0]
        lonval=""
        if len(mandatoryvars)>1:
            lonval=mandatoryvars[1]
        features = []
        first=True
        newobject=True
        item=""
        for result in results["results"]["bindings"]:
            if "item" in result and "rel" in result and "val" in result and (item=="" or result["item"]["value"]!=item) and "geo" in mandatoryvars:
                if item!="":
                    myGeometryInstance=QgsGeometry.fromWkt(result["geo"]["value"])
                    if reproject!="":
                        sourceCrs = QgsCoordinateReferenceSystem(reproject)
                        destCrs = QgsCoordinateReferenceSystem(4326)
                        tr = QgsCoordinateTransform(sourceCrs, destCrs, QgsProject.instance())
                        myGeometryInstance.transform(tr)
                    #feature = { 'type': 'Feature', 'properties': { 'label': result["label"]["value"], 'item': result["item"]["value"] }, 'geometry': wkt.loads(result["geo"]["value"].replace("Point", "POINT")) }
                    feature = { 'type': 'Feature', 'properties': properties, 'geometry':  json.loads(myGeometryInstance.asJson()) }
                    features.append(feature)
                properties = {}
                item=result["item"]["value"]
            #if not "rel" in result and not "val" in result:
            properties = {}
            for var in results["head"]["vars"]:
                if var in result:
                    if var=="rel" and "val" in result:
                        properties[result[var]["value"]] = result["val"]["value"]
                    elif var!="val":
                        properties[var] = result[var]["value"]
            if not "rel" in result and not "val" in result and "geo" in result:
                myGeometryInstance=QgsGeometry.fromWkt(result["geo"]["value"].replace("<http://www.opengis.net/def/crs/EPSG/0/"+reproject+"> ",""))
                if reproject!="":
                    sourceCrs = QgsCoordinateReferenceSystem(reproject)
                    destCrs = QgsCoordinateReferenceSystem(4326)
                    tr = QgsCoordinateTransform(sourceCrs, destCrs, QgsProject.instance())
                    myGeometryInstance.transform(tr)
                #feature = { 'type': 'Feature', 'properties': { 'label': result["label"]["value"], 'item': result["item"]["value"] }, 'geometry': wkt.loads(result["geo"]["value"].replace("Point", "POINT")) }
                feature = { 'type': 'Feature', 'properties': properties, 'geometry':  json.loads(myGeometryInstance.asJson()) }
                features.append(feature)
            if not "rel" in result and not "val" in result and latval in result and lonval in result and reproject==27700:
                myGeometryInstance = QgsGeometry.fromWkt("POINT("+str(float(result[latval]["value"]))+" "+str(float(result[lonval]["value"]))+")")
                if reproject!="":
                    sourceCrs = QgsCoordinateReferenceSystem(reproject)
                    destCrs = QgsCoordinateReferenceSystem(4326)
                    tr = QgsCoordinateTransform(sourceCrs, destCrs, QgsProject.instance())
                    myGeometryInstance.transform(tr)
                #feature = { 'type': 'Feature', 'properties': { 'label': result["label"]["value"], 'item': result["item"]["value"] }, 'geometry': wkt.loads(result["geo"]["value"].replace("Point", "POINT")) }
                feature = { 'type': 'Feature', 'properties': properties, 'geometry':  json.loads(myGeometryInstance.asJson()) }
                features.append(feature)
            if not "rel" in result and not "val" in result and latval in result and lonval in result and reproject!=27700:
                myGeometryInstance = QgsGeometry.fromWkt("POINT("+str(float(result[lonval]["value"]))+" "+str(float(result[latval]["value"]))+")")
                if reproject!="":
                    sourceCrs = QgsCoordinateReferenceSystem(reproject)
                    destCrs = QgsCoordinateReferenceSystem(4326)
                    tr = QgsCoordinateTransform(sourceCrs, destCrs, QgsProject.instance())
                    myGeometryInstance.transform(tr)
                #feature = { 'type': 'Feature', 'properties': { 'label': result["label"]["value"], 'item': result["item"]["value"] }, 'geometry': wkt.loads(result["geo"]["value"].replace("Point", "POINT")) }
                feature = { 'type': 'Feature', 'properties': properties, 'geometry':  json.loads(myGeometryInstance.asJson()) }
                features.append(feature)
            #print(properties)
        if "rel" in results["results"]["bindings"] and "val" in results["results"]["bindings"]:
            myGeometryInstance = QgsGeometry.fromWkt(result["geo"]["value"])
            if reproject!="":
                sourceCrs = QgsCoordinateReferenceSystem(reproject)
                destCrs = QgsCoordinateReferenceSystem(4326)
                tr = QgsCoordinateTransform(sourceCrs, destCrs, QgsProject.instance())
                myGeometryInstance.transform(tr)
            #feature = { 'type': 'Feature', 'properties': { 'label': result["label"]["value"], 'item': result["item"]["value"] }, 'geometry': wkt.loads(result["geo"]["value"].replace("Point", "POINT")) }
            feature = { 'type': 'Feature', 'properties': properties, 'geometry':  json.loads(myGeometryInstance.asJson()) }
            features.append(feature)
        if features==[]:
            return None
        geojson = {'type': 'FeatureCollection', 'features': features }
        return geojson

    def create_unicorn_layer(self):
        endpointIndex = self.dlg.comboBox.currentIndex()
        # SPARQL query
        #print(self.loadedfromfile)
		# query
        query = self.dlg.inp_sparql.toPlainText()
        if self.loadedfromfile:
            concept = self.dlg.layerconcepts.currentText()
            geojson=self.getGeoJSONFromGeoConcept(self.currentgraph,concept)
            vlayer = QgsVectorLayer(json.dumps(geojson, sort_keys=True, indent=4),"unicorn_"+self.dlg.inp_label.text(),"ogr")
            print(vlayer.isValid())
            QgsProject.instance().addMapLayer(vlayer)
            canvas = iface.mapCanvas()
            canvas.setExtent(vlayer.extent())
            iface.messageBar().pushMessage("Add layer", "OK", level=Qgis.Success)
            #iface.messageBar().pushMessage("Error", "An error occured", level=Qgis.Critical)
            self.dlg.close()
            return
        else:
            endpoint_url=self.triplestoreconf[endpointIndex]["endpoint"]
        missingmandvars=[]
        for mandvar in self.triplestoreconf[endpointIndex]["mandatoryvariables"]:
            if mandvar not in query:
                  missingmandvars.append("?"+mandvar)
        if missingmandvars!=[]:
            msgBox=QMessageBox()
            msgBox.setText("The SPARQL query is missing the following mandatory variables: "+str(missingmandvars))
            msgBox.exec()
        sparql = SPARQLWrapper(endpoint_url, agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11")
        sparql.setQuery("".join(self.triplestoreconf[endpointIndex]["prefixes"]) + query)
        sparql.setReturnFormat(JSON)
        try:
            results = sparql.query().convert()
        except Exception as e:
            msgBox=QMessageBox()
            msgBox.setText("The following exception occurred: "+str(e))
            msgBox.exec()
            return            
        #print(results)
        # geojson stuff
        geojson=self.processResults(results,(str(self.triplestoreconf[endpointIndex]["crs"]) if "crs" in self.triplestoreconf[endpointIndex] else ""),self.triplestoreconf[endpointIndex]["mandatoryvariables"][1:])
        if geojson==None:
            msgBox=QMessageBox()
            msgBox.setText("The query yielded no results. Therefore no layer will be created!")
            msgBox.exec()
            return
        # add layer
        vlayer = QgsVectorLayer(json.dumps(geojson, sort_keys=True, indent=4),"unicorn_"+self.dlg.inp_label.text(),"ogr")
        print(vlayer.isValid())
        QgsProject.instance().addMapLayer(vlayer)
        canvas = iface.mapCanvas()
        canvas.setExtent(vlayer.extent())
        iface.messageBar().pushMessage("Add layer", "OK", level=Qgis.Success)
        #iface.messageBar().pushMessage("Error", "An error occured", level=Qgis.Critical)
        self.dlg.close()

    def getGeoConcepts(self,triplestoreurl,query,queryvar,graph,getlabels):
        viewlist=[]
        resultlist=[]
        if graph!=None:
            results = graph.query(query)
            for row in results:
                viewlist.append(str(row[0]))
        else:
            sparql = SPARQLWrapper(triplestoreurl, agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11")
            sparql.setQuery(query)
            print("now sending query")
            sparql.setReturnFormat(JSON)
            results = sparql.query().convert()
            for result in results["results"]["bindings"]:
                viewlist.append(str(result[queryvar]["value"]))
        print(viewlist)
        self.dlg.layercount.setText("["+str(len(viewlist))+"]")
        if getlabels and "classlabelquery" in self.triplestoreconf[self.dlg.comboBox.currentIndex()] and self.triplestoreconf[self.dlg.comboBox.currentIndex()]["classlabelquery"]!="":
            labels=self.getLabelsForClasses(viewlist,self.triplestoreconf[self.dlg.comboBox.currentIndex()]["classlabelquery"],self.dlg.comboBox.currentIndex())
            print(labels)
            self.dlg.layercount.setText("["+str(len(labels))+"]")
            i=0
            sorted_labels=sorted(labels.items(),key=lambda x:x[1])
            for lab in sorted_labels:
                resultlist.append(labels[lab[0]]+"("+lab[0]+")")
                i=i+1	
            return resultlist
        return viewlist

    """Returns classes for a given label from a triple store."""
    def getClassesFromLabel(self):
        viewlist=[]
        resultlist=[]
        label=self.dlg.conceptSearchEdit.text()
        language="en"
        results={}
        self.dlg.searchResult.clear()
        query=""
        if self.dlg.currentcol==4:
            if "propertyfromlabelquery" in self.triplestoreconf[self.dlg.comboBox.currentIndex()]:
                query=self.triplestoreconf[self.dlg.comboBox.currentIndex()]["propertyfromlabelquery"].replace("%%label%%",label)
        else:
            if "classfromlabelquery" in self.triplestoreconf[self.dlg.comboBox.currentIndex()]:
                query=self.triplestoreconf[self.dlg.comboBox.currentIndex()]["classfromlabelquery"].replace("%%label%%",label)
        if "SELECT" in query:
            query=query.replace("%%label%%",label).replace("%%language%%",language)
            sparql = SPARQLWrapper(self.triplestoreconf[self.dlg.comboBox.currentIndex()]["endpoint"], agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11")
            sparql.setQuery(query)
            sparql.setReturnFormat(JSON)
            results = sparql.query().convert()
            for res in results["results"]["bindings"]:
                item=QListWidgetItem()
                item.setData(0,str(res["class"]["value"]))
                item.setText(str(res["label"]["value"]))
                self.dlg.searchResult.addItem(item)
        else:
            myResponse = json.loads(requests.get(query).text)
            for ent in myResponse["search"]:
                qid=ent["url"]
                label=ent["label"]+" ("+ent["id"]+") ["+ent["description"]+"]"
                results[qid]=label    
            for result in results:
                item=QListWidgetItem()
                item.setData(0,result)
                item.setText(str(results[result]))
                self.dlg.searchResult.addItem(item)
        return viewlist
	
    """Returns properties for a given label from a triple store.
    def getPropertiesFromLabel(self):
        viewlist=[]
        resultlist=[]
        sparql = SPARQLWrapper(triplestoreurl, agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11")
        sparql.setQuery(
        SELECT DISTINCT ?class
        WHERE {
          ?class <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Property> .
          ?class <http://www.w3.org/2000/01/rdf-schema#label> +"\""+label+"\"@"+language+ .
        }  LIMIT 500)
        print("now sending query")
        sparql.setReturnFormat(JSON)
        results = sparql.query().convert()
        for result in results["results"]["bindings"]:
            self.dlg.searchResult.addItem(str(result["class"]["value"]))
        return viewlist
    """

    def getLabelsForClasses(self,classes,query,endpointIndex):
        result={}
        query=self.triplestoreconf[endpointIndex]["classlabelquery"]
        #url="https://www.wikidata.org/w/api.php?action=wbgetentities&props=labels&ids="
        if "SELECT" in query:
            vals="VALUES ?class { "
            for qid in classes:
                vals+=qid+" "
            vals+="}\n"
            query=query.replace("%%concepts%%",vals)
            sparql = SPARQLWrapper(triplestoreurl, agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11")
            sparql.setQuery(query)
            sparql.setReturnFormat(JSON)
            results = sparql.query().convert()
            for res in results["results"]["bindings"]:
                result[res["class"]["value"]]=res["label"]["value"]
        else:
            url=self.triplestoreconf[self.dlg.comboBox.currentIndex()]["classlabelquery"]
            i=0
            qidquery=""
            for qid in classes:
                if "Q" in qid:
                    qidquery+="Q"+qid.split("Q")[1]
                if (i%50)==0:
                    print(url.replace("%%concepts%%",qidquery))
                    myResponse = json.loads(requests.get(url.replace("%%concepts%%",qidquery)).text)
                    print(myResponse)
                    for ent in myResponse["entities"]:
                        print(ent)
                        if "en" in myResponse["entities"][ent]["labels"]:
                            result[ent]=myResponse["entities"][ent]["labels"]["en"]["value"]                
                    qidquery=""
                else:
                    qidquery+="|"
                i=i+1
        return result

    def loadTripleStoreConfig(self):
        self.dlg.tripleStoreEdit.setText(self.triplestoreconf[self.dlg.tripleStoreChooser.currentIndex()]["endpoint"])
        self.dlg.tripleStoreNameEdit.setText(self.triplestoreconf[self.dlg.tripleStoreChooser.currentIndex()]["name"])
        self.dlg.prefixList.clear()
        for prefix in self.triplestoreconf[self.dlg.tripleStoreChooser.currentIndex()]["prefixes"]:
            self.dlg.prefixList.addItem(prefix)
        self.dlg.prefixList.sortItems()
        if "active" in self.triplestoreconf[self.dlg.tripleStoreChooser.currentIndex()]:
            self.dlg.activeCheckBox.setChecked(self.triplestoreconf[self.dlg.tripleStoreChooser.currentIndex()]["active"])
        if "crs" in self.triplestoreconf[self.dlg.tripleStoreChooser.currentIndex()]:
            self.dlg.epsgEdit.setText(str(self.triplestoreconf[self.dlg.tripleStoreChooser.currentIndex()]["crs"]))
        else:
            self.dlg.epsgEdit.setText("4326")
        self.dlg.exampleQuery.setPlainText(self.triplestoreconf[self.dlg.tripleStoreChooser.currentIndex()]["querytemplate"][0]["query"])

    def check_state1(self):
        self.check_state(self.dlg.tripleStoreEdit)

    def check_state2(self):
        self.check_state(self.dlg.tripleStorePrefixEdit)

    def check_state3(self):
        self.check_state(self.dlg.interlinkNameSpace)

    def check_state(self,sender):
        validator = sender.validator()
        state = validator.validate(sender.text(), 0)[0]
        if state == QValidator.Acceptable:
            color = '#c4df9b' # green
        elif state == QValidator.Intermediate:
            color = '#fff79a' # yellow
        else:
            color = '#f6989d' # red
        sender.setStyleSheet('QLineEdit { background-color: %s }' % color)

    def buildCustomTripleStoreDialog(self):	
        self.dlg.searchTripleStoreDialog = QDialog()	
        self.dlg.searchTripleStoreDialog.setMinimumSize(700, 500)	
        tripleStoreChooserLabel = QLabel("Choose Triple Store:",self.dlg.searchTripleStoreDialog)	
        tripleStoreChooserLabel.move(0,10)
        self.dlg.tripleStoreChooser=QComboBox(self.dlg.searchTripleStoreDialog)
        for item in self.triplestoreconf:
            self.dlg.tripleStoreChooser.addItem(item["name"])
        self.dlg.tripleStoreChooser.move(150,10)
        self.dlg.tripleStoreChooser.currentIndexChanged.connect(self.loadTripleStoreConfig)    
        addTripleStoreButton = QPushButton("Add new Triple Store",self.dlg.searchTripleStoreDialog)	
        addTripleStoreButton.move(350,10)	
        addTripleStoreButton.clicked.connect(self.addNewSPARQLEndpoint)	
        tripleStoreLabel = QLabel("Triple Store URL:",self.dlg.searchTripleStoreDialog)	
        tripleStoreLabel.move(0,40)	
        urlregex = QRegExp("http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+")
        urlvalidator = QRegExpValidator(urlregex, self.dlg.searchTripleStoreDialog)
        self.dlg.tripleStoreEdit = QLineEdit(self.dlg.searchTripleStoreDialog)	
        self.dlg.tripleStoreEdit.move(150,40)	
        self.dlg.tripleStoreEdit.setMinimumSize(350, 20)	
        self.dlg.tripleStoreEdit.setText("https://query.wikidata.org/sparql")
        self.dlg.tripleStoreEdit.setValidator(urlvalidator)
        self.dlg.tripleStoreEdit.textChanged.connect(self.check_state1)
        self.dlg.tripleStoreEdit.textChanged.emit(self.dlg.tripleStoreEdit.text())
        testConnectButton = QPushButton("Test Connection",self.dlg.searchTripleStoreDialog)	
        testConnectButton.move(510,40)	
        testConnectButton.clicked.connect(self.testTripleStoreConnection)	
        tripleStoreNameLabel = QLabel("Triple Store Name:",self.dlg.searchTripleStoreDialog)	
        tripleStoreNameLabel.move(0,70)	
        self.dlg.tripleStoreNameEdit = QLineEdit(self.dlg.searchTripleStoreDialog)	
        self.dlg.tripleStoreNameEdit.move(150,70)	
        self.dlg.tripleStoreNameEdit.setMinimumSize(350, 20)	
        self.dlg.tripleStoreNameEdit.setText("My cool triplestore!")	
        queryVarLabel = QLabel("Geometry Variable:",self.dlg.searchTripleStoreDialog)	
        queryVarLabel.move(10,105)	
        self.dlg.queryVarEdit = QLineEdit(self.dlg.searchTripleStoreDialog)	
        self.dlg.queryVarEdit.move(150,100)	
        self.dlg.queryVarEdit.setText("geo")	
        self.dlg.queryVarEdit.setMinimumSize(100, 20)	
        queryVarItemLabel = QLabel("Item Variable:",self.dlg.searchTripleStoreDialog)	
        queryVarItemLabel.move(305,105)	
        self.dlg.queryVarItemEdit = QLineEdit(self.dlg.searchTripleStoreDialog)	
        self.dlg.queryVarItemEdit.move(400,100)	
        self.dlg.queryVarItemEdit.setText("item")	
        self.dlg.queryVarItemEdit.setMinimumSize(100, 20)	
        epsgLabel = QLabel("EPSG Code:",self.dlg.searchTripleStoreDialog)	
        epsgLabel.move(10,125)	
        self.dlg.epsgEdit = QLineEdit(self.dlg.searchTripleStoreDialog)	
        self.dlg.epsgEdit.move(150,125)	
        self.dlg.epsgEdit.setText("4326")
        self.dlg.epsgEdit.setValidator(QIntValidator(1, 100000))
        self.dlg.epsgEdit.setMinimumSize(100, 20)
        activeTripleStore = QLabel("Active:",self.dlg.searchTripleStoreDialog)	
        activeTripleStore.move(310,125)	
        self.dlg.activeCheckBox = QCheckBox(self.dlg.searchTripleStoreDialog)	
        self.dlg.activeCheckBox.move(360,125)	
        prefixregex = QRegExp("[a-z]+")
        prefixvalidator = QRegExpValidator(prefixregex, self.dlg.searchTripleStoreDialog)
        self.dlg.tripleStorePrefixNameEdit = QLineEdit(self.dlg.searchTripleStoreDialog)	
        self.dlg.tripleStorePrefixNameEdit.move(150,150)	
        self.dlg.tripleStorePrefixNameEdit.setText("wd")	
        self.dlg.tripleStorePrefixNameEdit.setMinimumSize(100, 20)	
        self.dlg.tripleStorePrefixNameEdit.setValidator(prefixvalidator)
        tripleStorePrefixName = QLabel("Prefix:",self.dlg.searchTripleStoreDialog)	
        tripleStorePrefixName.move(10,150)	
        addPrefixButton = QPushButton("Add Prefix",self.dlg.searchTripleStoreDialog)	
        addPrefixButton.move(560,150)	
        addPrefixButton.clicked.connect(self.addPrefixToList)	
        removePrefixButton = QPushButton("Remove Selected Prefix",self.dlg.searchTripleStoreDialog)	
        removePrefixButton.move(100,180)
        removePrefixButton.clicked.connect(self.removePrefixFromList)	
        prefixListLabel = QLabel("Prefixes:",self.dlg.searchTripleStoreDialog)	
        prefixListLabel.move(20,185)	
        self.dlg.prefixList=QListWidget(self.dlg.searchTripleStoreDialog)	
        self.dlg.prefixList.move(20,210)	
        self.dlg.prefixList.setMinimumSize(300,200)	
        exampleQueryLabel = QLabel("Example Query (optional): ",self.dlg.searchTripleStoreDialog)	
        exampleQueryLabel.move(330,185)	
        self.dlg.exampleQuery=QPlainTextEdit(self.dlg.searchTripleStoreDialog)	
        self.dlg.exampleQuery.move(330,210)	
        self.dlg.exampleQuery.setMinimumSize(300,200)	
        self.dlg.exampleQuery.textChanged.connect(self.validateSPARQL)	
        sparqlhighlighter = SPARQLHighlighter(self.dlg.exampleQuery,self.dlg.errorLabel)	
        #self.dlg.queryChooser=QComboBox(self.dlg.searchTripleStoreDialog)
        self.dlg.tripleStorePrefixEdit = QLineEdit(self.dlg.searchTripleStoreDialog)	
        self.dlg.tripleStorePrefixEdit.move(310,150)	
        self.dlg.tripleStorePrefixEdit.setText("http://www.wikidata.org/entity/")	
        self.dlg.tripleStorePrefixEdit.setValidator(urlvalidator)
        self.dlg.tripleStorePrefixEdit.textChanged.connect(self.check_state2)
        self.dlg.tripleStorePrefixEdit.textChanged.emit(self.dlg.tripleStorePrefixEdit.text())
        self.dlg.tripleStorePrefixEdit.setMinimumSize(250, 20)
        tripleStoreApplyButton = QPushButton("Apply",self.dlg.searchTripleStoreDialog)	
        tripleStoreApplyButton.move(10,460)	
        tripleStoreApplyButton.clicked.connect(self.applyCustomSPARQLEndPoint)	
        tripleStoreCloseButton = QPushButton("Close",self.dlg.searchTripleStoreDialog)	
        tripleStoreCloseButton.move(100,460)	
        tripleStoreCloseButton.clicked.connect(self.closeTripleStoreDialog)	
        #tripleStoreApplyButton = QPushButton("Reset Configuration",self.dlg.searchTripleStoreDialog)	
        #tripleStoreApplyButton.move(330,560)	
        #tripleStoreApplyButton.clicked.connect(self.resetTripleStoreConfig)	
        self.dlg.searchTripleStoreDialog.setWindowTitle("Configure Own Triple Store")	
        self.dlg.searchTripleStoreDialog.exec_()	

    def closeTripleStoreDialog(self):
        self.dlg.searchTripleStoreDialog.close()

    def testTripleStoreConnection(self,calledfromotherfunction=False):	
        sparql = SPARQLWrapper(self.dlg.tripleStoreEdit.text(), agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11")	
        sparql.setQuery("SELECT ?a ?b ?c WHERE { ?a ?b ?c .} LIMIT 1")	
        sparql.setReturnFormat(JSON)	
        print("now sending query")	
        try:	
            results = sparql.query()	
            if not calledfromotherfunction:	
                msgBox=QMessageBox()	
                msgBox.setText("URL depicts a valid SPARQL Endpoint!")	
                msgBox.exec()	
            return True	
        except:	
            msgBox=QMessageBox()	
            msgBox.setText("URL does not depict a valid SPARQL Endpoint!")	
            msgBox.exec()	
            return False	

    def addNewSPARQLEndpoint(self):
        self.addTripleStore=True
        self.applyCustomSPARQLEndPoint()


    def addPrefixToList(self):	
        item=QListWidgetItem()	
        item.setData(0,"PREFIX "+self.dlg.tripleStorePrefixNameEdit.text()+":<"+self.dlg.tripleStorePrefixEdit.text()+">")	
        item.setText("PREFIX "+self.dlg.tripleStorePrefixNameEdit.text()+":<"+self.dlg.tripleStorePrefixEdit.text()+">")	
        self.dlg.prefixList.addItem(item)	

    def removePrefixFromList(self):	
        item=QListWidgetItem()	
        for item in self.dlg.prefixList.selectedItems():
            self.dlg.prefixList.removeItemWidget(item)

    def applyCustomSPARQLEndPoint(self):	
        if not self.testTripleStoreConnection(True):	
           return	
        if self.dlg.tripleStoreNameEdit.text()=="":	
           msgBox=QMessageBox()	
           msgBox.setText("Triple Store Name is missing!")	
           msgBox.exec()	
           return	
        #self.endpoints.append(self.dlg.tripleStoreEdit.text())	
        self.dlg.comboBox.addItem(self.dlg.tripleStoreNameEdit.text())	
        curprefixes=[]	
        for i in range(self.dlg.prefixList.count()):	
            curprefixes.append(self.dlg.prefixList.item(i).text()	)
        if self.addTripleStore:
            index=len(self.triplestoreconf)
            self.dlg.tripleStoreChooser.addItem(self.dlg.tripleStoreNameEdit.text()	)
            self.triplestoreconf.append({})
            self.triplestoreconf[index]["querytemplate"]=[]
            self.triplestoreconf[index]["querytemplate"].append({})
            self.triplestoreconf[index]["querytemplate"][0]["label"]="Example Query"
            self.triplestoreconf[index]["querytemplate"][0]["query"]=self.dlg.exampleQuery.toPlainText()
        else:
            index=self.dlg.tripleStoreChooser.currentIndex()
        self.triplestoreconf[index]={}
        self.triplestoreconf[index]["endpoint"]=self.dlg.tripleStoreEdit.text()
        self.triplestoreconf[index]["name"]=self.dlg.tripleStoreNameEdit.text()	
        self.triplestoreconf[index]["mandatoryvariables"]=[]
        self.triplestoreconf[index]["mandatoryvariables"].append(self.dlg.queryVarEdit.text())
        self.triplestoreconf[index]["mandatoryvariables"].append(self.dlg.queryVarItemEdit.text())        
        self.triplestoreconf[index]["prefixes"]=curprefixes
        self.triplestoreconf[index]["crs"]=self.dlg.epsgEdit.text()	
        self.triplestoreconf[index]["active"]=self.dlg.activeCheckBox.isChecked()

        self.addTripleStore=False

    def getGeoJSONFromGeoConcept(self,graph,concept):
        print(concept)
        qres = graph.query(
        """SELECT DISTINCT ?a ?rel ?val ?wkt
        WHERE {
          ?a rdf:type <"""+concept+"""> .
          ?a ?rel ?val .
          OPTIONAL { ?val <http://www.opengis.net/ont/geosparql#asWKT> ?wkt}
        }""")
        geos=[]
        geometries = {
            'type': 'FeatureCollection',
            'features': geos,
            }
        newfeature=False
        lastfeature=""
        currentgeo={}
        for row in qres:
            print(lastfeature+" - "+row[0]+" - "+str(len(row)))
            print(row)
            if(lastfeature=="" or lastfeature!=row[0]):
                if(lastfeature!=""):
                    geos.append(currentgeo)
                lastfeature=row[0]
                currentgeo={'id':row[0],'geometry':{},'properties':{}}
            if(row[3]!=None):
                print(row[3])
                if("<" in row[3]):
                    currentgeo['geometry']=json.loads(QgsGeometry.fromWkt(row[3].split(">")[1].strip()).asJson())
                else:
                    currentgeo['geometry']=json.loads(QgsGeometry.fromWkt(row[3]).asJson())
            else:
                currentgeo['properties'][str(row[1])]=str(row[2])
        return geometries

    def createEnrichSearchDialog(self,row=-1,column=-1):
        self.interlinkOrEnrich=False
        if column==1:
            self.buildSearchDialog(row,column)

    def createInterlinkSearchDialog(self, row=-1, column=-1):
        self.interlinkOrEnrich=True
        if column>3 or column==-1:
            self.buildSearchDialog(row,column)

    def buildSearchDialog(self,row,column):
        self.dlg.currentcol=column
        self.dlg.currentrow=row
        self.dlg.interlinkdialog = QDialog()
        self.dlg.interlinkdialog.setMinimumSize(650, 400)
        self.dlg.conceptSearchEdit = QLineEdit(self.dlg.interlinkdialog)
        self.dlg.conceptSearchEdit.move(100,10)
        conceptSearchLabel = QLabel("Search Concept:",self.dlg.interlinkdialog)
        conceptSearchLabel.move(0,10)
        findConcept = QRadioButton("Class",self.dlg.interlinkdialog)
        findConcept.move(300,15)
        if column!=4:
            findConcept.setChecked(True)
        findProperty = QRadioButton("Property",self.dlg.interlinkdialog)
        findProperty.move(300,40)
        if column==4:
            findProperty.setChecked(True)
        findProperty.setEnabled(False)
        findConcept.setEnabled(False)
        self.dlg.tripleStoreEdit = QComboBox(self.dlg.interlinkdialog)
        self.dlg.tripleStoreEdit.move(100,40)
        for triplestore in self.triplestoreconf:
            if not "File"==triplestore["name"]:
                self.dlg.tripleStoreEdit.addItem(triplestore["name"])
        tripleStoreLabel = QLabel("Triple Store:",self.dlg.interlinkdialog)
        tripleStoreLabel.move(0,40)
        searchButton = QPushButton("Search",self.dlg.interlinkdialog)
        searchButton.move(10,70)
        searchButton.clicked.connect(self.getClassesFromLabel)
        searchResultLabel = QLabel("Search Results",self.dlg.interlinkdialog)
        searchResultLabel.move(100,100)
        self.dlg.searchResult = QListWidget(self.dlg.interlinkdialog)
        self.dlg.searchResult.move(30,120)
        self.dlg.searchResult.setMinimumSize(600, 300)
        applyButton = QPushButton("Apply",self.dlg.interlinkdialog)
        applyButton.move(150,430)
        applyButton.clicked.connect(self.applyConceptToColumn)
        self.dlg.interlinkdialog.setWindowTitle("Search Interlink Concept")
        self.dlg.interlinkdialog.exec_()

    def applyConceptToColumn(self):
        print("test")
        if self.dlg.currentrow==-1 and self.dlg.currentcol==-1:
            self.dlg.interlinkOwlClassInput.setText(str(self.dlg.searchResult.currentItem().data(0)))
        else:
            item=QTableWidgetItem(self.dlg.searchResult.currentItem().text())
            item.setText(self.dlg.searchResult.currentItem().text())
            item.setData(0,self.dlg.searchResult.currentItem().data(0))
            if self.interlinkOrEnrich:
                self.dlg.interlinkTable.setItem(self.dlg.currentrow,self.dlg.currentcol,item)
            else:
                item2=QTableWidgetItem()
                item2.setText(self.dlg.tripleStoreEdit.currentText())
                item2.setData(0,self.triplestoreconf[self.dlg.tripleStoreEdit.currentIndex()+1]["endpoint"])
                self.dlg.enrichTable.setItem(self.dlg.currentrow,self.dlg.currentcol,item)
                self.dlg.enrichTable.setItem(self.dlg.currentrow,(self.dlg.currentcol+1),item2)
        self.dlg.interlinkdialog.close()

    def addnewEnrichRow(self):
        currentRowCount = self.dlg.enrichTable.rowCount() 
        self.dlg.enrichTable.insertRow(currentRowCount)
        
    def moveRow(self,upOrDown):
        if self.dlg.enrichTable.selectionModel().hasSelected():
            currentRowCount = self.dlg.enrichTable.selectedRows() 

    def loadLayerForEnrichment(self):
        layers = QgsProject.instance().layerTreeRoot().children()
        selectedLayerIndex = self.dlg.chooseLayerEnrich.currentIndex()
        layer = layers[selectedLayerIndex].layer()
        self.dlg.IDColumnEnrich.clear()
        self.dlg.enrichTableResult.hide()
        self.dlg.enrichTable.show()
        self.dlg.addEnrichedLayerRowButton.setEnabled(True)
        fieldnames = [field.name() for field in layer.fields()]
        while self.dlg.enrichTable.rowCount() > 0:
            self.dlg.enrichTable.removeRow(0);
        row=0
        self.dlg.enrichTable.setColumnCount(6)
        self.dlg.enrichTable.setHorizontalHeaderLabels(["Column","EnrichmentConcept","TripleStore","Strategy","content","Options"])
        for field in fieldnames:
            item=QTableWidgetItem(field)
            item.setFlags(QtCore.Qt.ItemIsEnabled)
            currentRowCount = self.dlg.enrichTable.rowCount() 
            self.dlg.IDColumnEnrich.addItem(field)
            self.dlg.enrichTable.insertRow(row)
            self.dlg.enrichTable.setItem(row,0,item)
            cbox=QComboBox()
            cbox.addItem("No Enrichment")
            cbox.addItem("Keep Local")
            cbox.addItem("Keep Remote")
            cbox.addItem("Replace Local")
            cbox.addItem("Merge")
            cbox.addItem("Ask User")
            cbox.addItem("Exclude")
            self.dlg.enrichTable.setCellWidget(row,3,cbox)
            cbox=QComboBox()	
            cbox.addItem("Enrich Value")	
            cbox.addItem("Enrich URI")	
            cbox.addItem("Enrich Both")	
            self.dlg.enrichTable.setCellWidget(row,4,cbox)
            celllayout= QHBoxLayout()
            upbutton=QPushButton("Up")
            removebutton=QPushButton("Remove")
            removebutton.clicked.connect(self.deleteEnrichRow)
            downbutton=QPushButton("Down")
            celllayout.addWidget(upbutton)
            celllayout.addWidget(downbutton)
            celllayout.addWidget(removebutton)
            w = QWidget()
            w.setLayout(celllayout)
            optitem=QTableWidgetItem()
            #self.dlg.enrichTable.setCellWidget(row,4,w)
            #self.dlg.enrichTable.setItem(row,3,cbox)
            row+=1

    def deleteEnrichRow(send):
        w = send.sender().parent()
        row = self.dlg.enrichTable.indexAt(w.pos()).row()
        self.dlg.enrichTable.removeRow(row);
        self.dlg.enrichTable.setCurrentCell(0, 0)
        
    def addEnrichRow(self):
        item=QTableWidgetItem("new_column")
        item.setFlags(QtCore.Qt.ItemIsEnabled)
        row = self.dlg.enrichTable.rowCount() 
        self.dlg.IDColumnEnrich.addItem("new_column")
        self.dlg.enrichTable.insertRow(row)
        self.dlg.enrichTable.setItem(row,0,item)
        cbox=QComboBox()
        cbox.addItem("Get Remote")
        cbox.addItem("No Enrichment")
        cbox.addItem("Exclude")
        self.dlg.enrichTable.setCellWidget(row,3,cbox)

    def enrichLayer(self):
        layers = QgsProject.instance().layerTreeRoot().children()
        selectedLayerIndex = self.dlg.chooseLayerEnrich.currentIndex()
        self.enrichLayer = layers[selectedLayerIndex].layer().clone()
        attlist={}
        itemlist=[]
        propertylist=[]
        excludelist=[]
        idfield=self.dlg.IDColumnEnrich.currentText()
        for row in range(self.dlg.enrichTable.rowCount()):
            item = self.dlg.enrichTable.item(row, 0).text()
            property=self.dlg.enrichTable.item(row, 1)
            strategy = self.dlg.enrichTable.cellWidget(row, 3).currentText()
            if item!=idfield:
                propertylist.append(self.dlg.enrichTable.item(row, 1)) 
            if strategy=="Exclude":
                excludelist.append(row)
            if strategy!="No Enrichment" and property!=None:
                itemlist.append(item)
                attlist[item]=[]
                for f in self.enrichLayer.getFeatures():
                    attlist[item].append(f[item])
                if content=="Enrich URI": 
                    query="SELECT ?item WHERE {\n"
                elif content=="Enrich Value" or content=="Enrich Both":
                    query="SELECT ?item ?val ?valLabel WHERE {\n"
                query+="VALUES ?item { "
                for it in attlist[idfield]:
                    query+=it
                query+=" } . \n"
                query+="?item <"+property+"> ?val . \n"
                if (content=="Enrich Value" or content=="Enrich Both") and not "wikidata" in triplestoreurl:
                    query+="OPTIONAL{ ?val rdfs:label ?valLabel }"
                elif (content=="Enrich Value" or content=="Enrich Both") and "wikidata" in triplestoreurl:
                    query+="SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE],en\". }\n"
                query+="} ORDER BY ?item "
                sparql = SPARQLWrapper(triplestoreurl, agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11")
                sparql.setQuery(query)
                print("now sending query")
                sparql.setReturnFormat(JSON)
                results = sparql.query().convert()
                resultcounter=0
                for f in self.enrichLayer.getFeatures():
                    if strategy=="Keep Local" and f[item]=="" and results["results"]["bindings"][resultcounter]["val"]["value"]!="":
                        if content=="Enrich Value":
                            f[item]=results["results"]["bindings"][resultcounter]["valLabel"]["value"]
                        elif content=="Enrich URI":
                            f[item]=results["results"]["bindings"][resultcounter]["val"]["value"]
                        else:
                            f[item]=results["results"]["bindings"][resultcounter]["valLabel"]["value"]+";"+results["results"]["bindings"][resultcounter]["val"]["val"]
                    elif strategy=="Replace Local" and results["results"]["bindings"][resultcounter]["val"]["value"]!="":
                        if content=="Enrich Value":
                            f[item]=results["results"]["bindings"][resultcounter]["valLabel"]["value"]
                        elif content=="Enrich URI":
                            f[item]=results["results"]["bindings"][resultcounter]["val"]["value"]
                        else:
                            f[item]=results["results"]["bindings"][resultcounter]["valLabel"]["value"]+";"+results["results"]["bindings"][resultcounter]["val"]["value"]
                    elif strategy=="Merge":
                        if content=="Enrich Value":
                            f[item]=str(f[item])+";"+str(results["results"]["bindings"][resultcounter]["valLabel"]["value"])
                        elif content=="Enrich URI":
                            f[item]=str(f[item])+";"+str(results["results"]["bindings"][resultcounter]["val"]["value"])
                        else:
                            f[item]=str(f[item])+";"+results["results"]["bindings"][resultcounter]["valLabel"]["value"]+";"+results["results"]["bindings"][resultcounter]["val"]["value"]                       
                    elif strategy=="Ask User":
                        print("Asking user")
                    resultcounter+=1
            row+=1
        self.enrichLayer.dataProvider().deleteAttributes(excludelist)
        self.enrichLayer.updateFields()
        self.dlg.enrichTable.hide()
        fieldnames = [field.name() for field in self.enrichLayer.fields()]
        self.dlg.enrichTableResult.clear()
        self.dlg.enrichTableResult.setRowCount(0)		
        self.dlg.enrichTableResult.setColumnCount(len(fieldnames))
        self.dlg.enrichTableResult.setHorizontalHeaderLabels(fieldnames)
        row=0
        for f in self.enrichLayer.getFeatures():
            fieldcounter=0
            self.dlg.enrichTableResult.insertRow(row)
            for field in f:
                item=QTableWidgetItem(field)
                self.dlg.enrichTableResult.setItem(row,fieldcounter,item)
                #if ";" in field:
                    #item.setBackground(QColor.red)
                fieldcounter+=1
            row+=1
        self.dlg.enrichTableResult.show()
        self.dlg.addEnrichedLayerRowButton.setEnabled(False)


    def addEnrichedLayer(self):
        QgsProject.instance().addMapLayer(self.enrichLayer)
        canvas = iface.mapCanvas()
        canvas.setExtent(self.enrichLayer.extent())
        iface.messageBar().pushMessage("Add layer", "OK", level=Qgis.Success)
        #iface.messageBar().pushMessage("Error", "An error occured", level=Qgis.Critical)
        self.dlg.close()

    def loadLayerForInterlink(self):
        layers = QgsProject.instance().layerTreeRoot().children()
        selectedLayerIndex = self.dlg.chooseLayerInterlink.currentIndex()
        layer = layers[selectedLayerIndex].layer()
        fieldnames = [field.name() for field in layer.fields()]
        while self.dlg.interlinkTable.rowCount() > 0:
            self.dlg.interlinkTable.removeRow(0);
        row=0
        self.dlg.interlinkTable.setHorizontalHeaderLabels(["Export?","IDColumn?","GeoColumn?","Column","ColumnProperty","ColumnConcept","ValueConcepts"])
        self.dlg.interlinkTable.setColumnCount(7)
        for field in fieldnames:
            item=QTableWidgetItem(field)
            item.setFlags(QtCore.Qt.ItemIsEnabled)
            item2=QTableWidgetItem()
            item2.setCheckState(True)
            item3=QTableWidgetItem()
            item3.setCheckState(False)
            item4=QTableWidgetItem()
            item4.setCheckState(False)
            currentRowCount = self.dlg.interlinkTable.rowCount() 
            self.dlg.interlinkTable.insertRow(row)
            self.dlg.interlinkTable.setItem(row,3,item)
            self.dlg.interlinkTable.setItem(row,0,item2)
            self.dlg.interlinkTable.setItem(row,1,item3)
            self.dlg.interlinkTable.setItem(row,2,item4)
            row+=1

    def exportEnrichedLayer(self):
        self.exportIdCol=""
        self.exportNameSpace=self.dlg.interlinkNameSpace.text()
        self.exportSetClass=self.dlg.interlinkOwlClassInput.text()
        for row in range(self.dlg.interlinkTable.rowCount()):
            item = self.dlg.interlinkTable.item(row, 0)
            if item.checkState():
                if self.dlg.interlinkTable.item(row, 1).checkState():
                    self.exportIdCol=self.dlg.interlinkTable.item(row, 3).text()
                else:
                    column = self.dlg.interlinkTable.item(row, 3).text()
                    if self.dlg.interlinkTable.item(row,4)!=None:
                        column=self.dlg.interlinkTable.item(row,4).data(0)
                    if self.dlg.interlinkTable.item(row, 5)!=None:
                        concept = self.dlg.interlinkTable.item(row, 5).data(0)
                        self.exportColConfig[column]=concept
                    if self.dlg.interlinkTable.item(row, 6)!=None:
                        valueconcept = self.dlg.interlinkTable.item(row, 6).data(0)
        self.enrichedExport=True
        self.exportLayer()
		
    def matchColumnValueFromTripleStore(self,toquery):
        values="VALUES ?vals { "
        for queryval in toquery:
            values+="\""+queryval+"\""
        values+="}"
        sparql = SPARQLWrapper("https://query.wikidata.org/sparql", agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11")
        sparql.setQuery(
        """SELECT DISTINCT ?a
        WHERE {
          ?a wdt:P31 ?class .
          ?a ?label ?vals .
        } """)
        sparql.setReturnFormat(JSON)
        results = sparql.query().convert()
        for result in results["results"]["bindings"]:
            viewlist.append(str(result["a"]["value"]))
        return viewlist
		

    def exportLayer(self):
        filename, _filter = QFileDialog.getSaveFileName(
            self.dlg, "Select   output file ","", "Linked data (*.rdfxml *.ttl *.n3 *.owl *.nt *.nq *.trix *.json-ld)",)
        if filename=="":
             return
        layers = QgsProject.instance().layerTreeRoot().children()
        if self.enrichedExport:
            selectedLayerIndex = self.dlg.chooseLayerInterlink.currentIndex()
        else:
            selectedLayerIndex = self.dlg.loadedLayers.currentIndex()
        layer = layers[selectedLayerIndex].layer()
        fieldnames = [field.name() for field in layer.fields()]
        ttlstring="<http://www.opengis.net/ont/geosparql#Feature> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Class> .\n"
        ttlstring+="<http://www.opengis.net/ont/geosparql#SpatialObject> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Class> .\n"
        ttlstring+="<http://www.opengis.net/ont/geosparql#Geometry> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Class> .\n"
        ttlstring+="<http://www.opengis.net/ont/geosparql#hasGeometry> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#ObjectProperty> .\n"
        ttlstring+="<http://www.opengis.net/ont/geosparql#asWKT> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#DatatypeProperty> .\n"
        ttlstring+="<http://www.opengis.net/ont/geosparql#Feature> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.opengis.net/ont/geosparql#SpatialObject> .\n"
        ttlstring+="<http://www.opengis.net/ont/geosparql#Geometry> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.opengis.net/ont/geosparql#SpatialObject> .\n"
        first=0
        if self.exportNameSpace=="":
            namespace="http://www.github.com/sparqlunicorn#"
        else:
            namespace=self.exportNameSpace
        if self.exportIdCol=="":
            idcol="id"
        else:
            idcol=self.exportIdCol
        classcol="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
        curid=""
        if self.exportSetClass=="":
            curclassid=namespace+str(uuid.uuid4())
        else:
            curclassid=self.exportSetClass
        for f in layer.getFeatures():
            geom = f.geometry()
            if not idcol in fieldnames:
                curid=namespace+str(uuid.uuid4())
            else:				 
                curid=f[idcol]
            if not classcol in fieldnames:
                ttlstring+="<"+curid+"> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <"+curclassid+"> .\n"
                if first==0:
                    ttlstring+="<"+curclassid+"> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.opengis.net/ont/geosparql#Feature> .\n"
                    ttlstring+="<"+curclassid+"> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Class> .\n"
            ttlstring+="<"+curid+"> <http://www.opengis.net/ont/geosparql#hasGeometry> <"+curid+"_geom> .\n"
            ttlstring+="<"+curid+"_geom> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.opengis.net/ont/geosparql#"+QgsWkbTypes.displayString(geom.wkbType())+"> .\n"
            ttlstring+="<http://www.opengis.net/ont/geosparql#"+QgsWkbTypes.displayString(geom.wkbType())+"> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Class> .\n"
            ttlstring+="<http://www.opengis.net/ont/geosparql#"+QgsWkbTypes.displayString(geom.wkbType())+"> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.opengis.net/ont/geosparql#Geometry> .\n"
            ttlstring+="<"+curid+"_geom> <http://www.opengis.net/ont/geosparql#asWKT> \""+geom.asWkt()+"\"^^<http://www.opengis.net/ont/geosparql#wktLiteral> .\n"
            for prop in fieldnames:
                if prop=="http://www.w3.org/1999/02/22-rdf-syntax-ns#type" and "http" in f[prop]:
                    ttlstring+="<"+f[prop]+"> <"+prop+"> <http://www.w3.org/2002/07/owl#Class> .\n"
                    ttlstring+="<"+f[prop]+"> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.opengis.net/ont/geosparql#Feature> .\n"
                if prop=="id":
                    continue
                elif prop=="http://www.w3.org/2000/01/rdf-schema#label" or prop=="http://www.w3.org/2000/01/rdf-schema#comment":
                    ttlstring+="<"+curid+"> <"+prop+"> \""+str(f[prop]).replace('"','\\"')+"\"^^<http://www.w3.org/2001/XMLSchema#string> .\n"
                    if first<10:
                        ttlstring+="<"+prop+"> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#AnnotationProperty> .\n" 
                        ttlstring+="<"+prop+"> <http://www.w3.org/2000/01/rdf-schema#domain> <"+curclassid+"> .\n"  						
                elif not f[prop] or f[prop]==None or f[prop]=="":
                    continue
                elif re.match(r'^-?\d+$', str(f[prop])):
                    ttlstring+="<"+curid+"> <"+prop+"> \""+str(f[prop])+"\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
                    if first<10:
                        ttlstring+="<"+prop+"> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#DatatypeProperty> .\n"
                        ttlstring+="<"+prop+"> <http://www.w3.org/2000/01/rdf-schema#domain> <"+curclassid+"> .\n" 
                        ttlstring+="<"+prop+"> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2001/XMLSchema#integer> .\n" 
                elif re.match(r'^-?\d+(?:\.\d+)?$', str(f[prop])):
                    ttlstring+="<"+curid+"> <"+prop+"> \""+str(f[prop])+"\"^^<http://www.w3.org/2001/XMLSchema#double> .\n"
                    if first:
                        ttlstring+="<"+prop+"> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#DatatypeProperty> .\n"
                        ttlstring+="<"+prop+"> <http://www.w3.org/2000/01/rdf-schema#domain> <"+curclassid+"> .\n" 
                        ttlstring+="<"+prop+"> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2001/XMLSchema#double> .\n" 
                elif "http" in f[prop]:
                    ttlstring+="<"+curid+"> <"+prop+"> <"+str(f[prop])+"> .\n"
                    if first<10:
                        ttlstring+="<"+prop+"> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#ObjectProperty> .\n"
                        ttlstring+="<"+prop+"> <http://www.w3.org/2000/01/rdf-schema#domain> <"+curclassid+"> .\n" 
                else:
                    ttlstring+="<"+curid+"> <"+prop+"> \""+str(f[prop]).replace('"','\\"')+"\"^^<http://www.w3.org/2001/XMLSchema#string> .\n"
                    if first<10:
                        ttlstring+="<"+prop+"> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#DatatypeProperty> .\n"
                        ttlstring+="<"+prop+"> <http://www.w3.org/2000/01/rdf-schema#domain> <"+curclassid+"> .\n" 
                        ttlstring+="<"+prop+"> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2001/XMLSchema#string> .\n" 
            if first<10:
                first=first+1
#        with open(filename+"_temp", 'w') as output_file:
#            output_file.write(ttlstring)
        g=rdflib.Graph()
        g.parse(data=ttlstring, format="ttl")
        splitted=filename.split(".")
        exportNameSpace=""
        exportSetClass=""
        with open(filename, 'w') as output_file:
            output_file.write(g.serialize(format=splitted[len(splitted)-1]).decode("utf-8"))
            iface.messageBar().pushMessage("export layer successfully!", "OK", level=Qgis.Success)

    def exportLayerAsGeoJSONLD(self):
        context={
    "geojson": "https://purl.org/geojson/vocab#",
    "Feature": "geojson:Feature",
    "FeatureCollection": "geojson:FeatureCollection",
    "GeometryCollection": "geojson:GeometryCollection",
    "LineString": "geojson:LineString",
    "MultiLineString": "geojson:MultiLineString",
    "MultiPoint": "geojson:MultiPoint",
    "MultiPolygon": "geojson:MultiPolygon",
    "Point": "geojson:Point",
    "Polygon": "geojson:Polygon",
    "bbox": {
      "@container": "@list",
      "@id": "geojson:bbox"
    },
    "coordinates": {
      "@container": "@list",
      "@id": "geojson:coordinates"
    },
    "features": {
      "@container": "@set",
      "@id": "geojson:features"
    },
    "geometry": "geojson:geometry",
    "id": "@id",
    "properties": "geojson:properties",
    "type": "@type",
    "description": "http://purl.org/dc/terms/description",
    "title": "http://purl.org/dc/terms/title"
  }
        layer = layers[selectedLayerIndex].layer()
        fieldnames = [field.name() for field in layer.fields()]
        currentgeo={}
        geos=[]
        for f in layer.getFeatures():
            geom = f.geometry()
            currentgeo={'id':row[0],'geometry':json.loads(geom.asJson()),'properties':{}}
            for prop in fieldnames:
                if prop=="id":
                    currentgeo["id"]=f[prop]
                else:
                    currentgeo["properties"][prop]=f[prop]
            geos.append(currentgeo)
        featurecollection={"@context":context, "type":"FeatureCollection", "@id":"http://example.com/collections/1", "features": geos }
        return featurecollection	

    def loadGraph(self):
        dialog = QFileDialog(self.dlg)
        dialog.setFileMode(QFileDialog.AnyFile)
        self.justloadingfromfile=True
        if dialog.exec_():
            fileNames = dialog.selectedFiles()
            g = rdflib.Graph()
            filepath=fileNames[0].split(".")
            result = g.parse(fileNames[0], format=filepath[len(filepath)-1])
            print(g)
            self.currentgraph=g
            geoconcepts=self.getGeoConcepts("",self.triplestoreconf[0]["geoconceptquery"],"class",g,False)
            self.dlg.layerconcepts.clear()
            for geo in geoconcepts:
                self.dlg.layerconcepts.addItem(geo)
            comp=QCompleter(self.dlg.layerconcepts)
            comp.setCompletionMode(QCompleter.PopupCompletion)
            comp.setModel(self.dlg.layerconcepts.model())
            self.dlg.layerconcepts.setCompleter(comp)
            self.dlg.inp_sparql.setPlainText(self.triplestoreconf[0]["querytemplate"][0]["query"].replace("%%concept%%",geoconcepts[0]))
            self.loadedfromfile=True
            self.justloadingfromfile=False
            self.dlg.comboBox.setCurrentIndex(0)
            return result
        return None
    """
    def loadGraph(self):
        dialog = QFileDialog(self.dlg)
        dialog.setFileMode(QFileDialog.AnyFile)
        self.justloadingfromfile=True
        if dialog.exec_():
            fileNames = dialog.selectedFiles()
            g = rdflib.Graph()
            filepath=fileNames[0].split(".")
            result = g.parse(fileNames[0], format=filepath[len(filepath)-1])
            print(g)
            self.currentgraph=g
            self.dlg.layerconcepts.clear()
            worker_thread = GeoConceptsThread(self.triplestoreconf[0]["geoconceptquery"],"",g)
            worker_thread.finished.connect(self.loadGraphGUI)
            worker_thread.start()
            #geoconcepts=self.getGeoConcepts("",self.triplestoreconf[0]["geoconceptquery"],"class",g)
        #return None

    def loadGraph(self):
        dialog = QFileDialog(self.dlg)
        dialog.setFileMode(QFileDialog.AnyFile)
        self.justloadingfromfile=True
        if dialog.exec_():
            fileNames = dialog.selectedFiles()
            g = rdflib.Graph()
            filepath=fileNames[0].split(".")
            result = g.parse(fileNames[0], format=filepath[len(filepath)-1])
            print(g)
            self.currentgraph=g
            self.dlg.layerconcepts.clear()
            worker = GeoConceptsWorker(self.triplestoreconf[0]["geoconceptquery"],"",g)
            worker_thread = QThread()
            worker.moveToThread(worker_thread)
            worker_thread.finished.connect(self.loadGraphGUI)
            worker_thread.start()
            #geoconcepts=self.getGeoConcepts("",self.triplestoreconf[0]["geoconceptquery"],"class",g)
        #return None
    """
    
    def loadGraphGUI(self):
        self.dlg.layercount.setText("["+str(len(viewlist))+"]")		
        for geo in geoconcepts:
            self.dlg.layerconcepts.addItem(geo)
        comp=QCompleter(self.dlg.layerconcepts)
        comp.setCompletionMode(QCompleter.PopupCompletion)
        comp.setModel(self.dlg.layerconcepts.model())
        self.dlg.layerconcepts.setCompleter(comp)
        self.dlg.inp_sparql.setPlainText(self.triplestore[0]["querytemplate"][0]["query"].replace("%%concept%%",geoconcepts[0]))
        self.loadedfromfile=True
        self.justloadingfromfile=False
        return result
    
    def getWikidataAreaConcepts(self):
        resultlist=[]
        resultlist.append("city"+" (Q515)")
        resultlist.append("country"+" (Q6256)")		
        return resultlist
		
    def loadAreas(self):
        resultlist=[]
        return resultlist
    
    def loadUnicornLayers(self):
        # Fetch the currently loaded layers
        layers = QgsProject.instance().layerTreeRoot().children()
        # Populate the comboBox with names of all the loaded unicorn layers
        self.dlg.loadedLayers.clear()
        self.dlg.chooseLayerInterlink.clear()
        self.dlg.chooseLayerEnrich.clear()
        for layer in layers:
            ucl = layer.name()
            #if type(layer) == QgsMapLayer.VectorLayer:
            self.dlg.loadedLayers.addItem(layer.name())
            self.dlg.chooseLayerInterlink.addItem(layer.name())
            self.dlg.chooseLayerEnrich.addItem(layer.name())       

    def endpointselectaction(self):
        endpointIndex = self.dlg.comboBox.currentIndex()
        self.dlg.queryTemplates.clear()
        print("changing endpoint")
        conceptlist=[]
        if "endpoint" in self.triplestoreconf[endpointIndex] and self.triplestoreconf[endpointIndex]["endpoint"]!="" 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"]!="":
            self.dlg.layerconcepts.clear()
            conceptlist=self.getGeoConcepts(self.triplestoreconf[endpointIndex]["endpoint"],self.triplestoreconf[endpointIndex]["geoconceptquery"],"class",None,True)
        elif "staticconcepts" in self.triplestoreconf[endpointIndex] and self.triplestoreconf[endpointIndex]["staticconcepts"]!=[]:
            self.dlg.layerconcepts.clear()
            conceptlist=self.triplestoreconf[endpointIndex]["staticconcepts"]
        for concept in conceptlist:
            self.dlg.layerconcepts.addItem(concept)
        comp=QCompleter(self.dlg.layerconcepts)
        comp.setCompletionMode(QCompleter.PopupCompletion)
        comp.setModel(self.dlg.layerconcepts.model())
        self.dlg.layerconcepts.setCompleter(comp)
        if "areaconcepts" in self.triplestoreconf[endpointIndex] and self.triplestoreconf[endpointIndex]["areaconcepts"]:
            conceptlist2=self.triplestoreconf[endpointIndex]["areaconcepts"]
            for concept in conceptlist2:
                 self.dlg.areaconcepts.addItem(concept)
        if "querytemplate" in self.triplestoreconf[endpointIndex]:
            for concept in self.triplestoreconf[endpointIndex]["querytemplate"]:
                 self.dlg.queryTemplates.addItem(concept["label"])
        if "examplequery" in self.triplestoreconf[endpointIndex]:
            self.dlg.inp_sparql.setPlainText(self.triplestoreconf[endpointIndex]["examplequery"]) 

    def setBBOXExtentQuery(self):	
        self.mts_layer=QgsProject.instance().layerTreeRoot().children()[self.chooseBBOXLayer.currentIndex()].layer()	
        self.layerExtentOrBBOX=True	
        self.setBBOXInQuery()

    def setBBOXInQuery(self):
        if self.layerExtentOrBBOX:
            xMax=self.mts_layer.extent().xMaximum()
            xMin=self.mts_layer.extent().xMinimum()
            yMin=self.mts_layer.extent().yMinimum()
            yMax=self.mts_layer.extent().yMaximum()
            pointt1=QgsGeometry.fromPointXY(QgsPointXY(xMax,yMin))	
            pointt2=QgsGeometry.fromPointXY(QgsPointXY(xMin,yMin))	
            pointt3=QgsGeometry.fromPointXY(QgsPointXY(xMin,yMax))	
            pointt4=QgsGeometry.fromPointXY(QgsPointXY(xMax,yMax))	
            sourceCrs = QgsCoordinateReferenceSystem(self.mts_layer.sourceCrs())	
        else:	
            pointt1=QgsGeometry.fromWkt(self.rect_tool.point1.asWkt())	
            pointt2=QgsGeometry.fromWkt(self.rect_tool.point2.asWkt())	
            pointt3=QgsGeometry.fromWkt(self.rect_tool.point3.asWkt())	
            pointt4=QgsGeometry.fromWkt(self.rect_tool.point4.asWkt())	
            sourceCrs = QgsCoordinateReferenceSystem(self.mts_layer.crs())
        destCrs = QgsCoordinateReferenceSystem(4326)
        tr = QgsCoordinateTransform(sourceCrs, destCrs, QgsProject.instance())
        pointt1.transform(tr)
        pointt2.transform(tr)
        pointt3.transform(tr)
        pointt4.transform(tr)
        polygon = QgsGeometry.fromPolylineXY( [pointt1.asPoint(),pointt2.asPoint(),pointt3.asPoint(),pointt4.asPoint()] )
        center=polygon.centroid()
        #distance = QgsDistanceArea()
        #distance.setSourceCrs(destCrs)
        #distance.setEllipsoidalMode(True)
        #distance.setEllipsoid('WGS84')
        widthm = 100 #distance.measureLine(pointt1, pointt2)
        self.curbbox=[]
        self.curbbox.append(pointt1)
        self.curbbox.append(pointt2)
        self.curbbox.append(pointt3)
        self.curbbox.append(pointt4)
        self.d.close()
        curquery=self.dlg.inp_sparql.toPlainText()
        endpointIndex = self.dlg.comboBox.currentIndex()
        if "bboxquery" in self.triplestoreconf[endpointIndex] and self.triplestoreconf[endpointIndex]["bboxquery"]["type"]=="minmax":
             curquery=curquery[0:curquery.rfind('}')]+self.triplestoreconf[endpointIndex]["bboxquery"]["query"].replace("%%minPoint%%",pointt2.asWKT()).replace("%%maxPoint%%",pointt4.asWkt())+curquery[curquery.rfind('}')+1:]
        elif "bboxquery" in self.triplestoreconf[endpointIndex] and self.triplestoreconf[endpointIndex]["bboxquery"]["type"]=="pointdistance":
            curquery=curquery[0:curquery.rfind('}')]+self.triplestoreconf[endpointIndex]["bboxquery"]["query"].replace("%%lat%%",str(center.asPoint().y())).replace("%%lon%%",str(center.asPoint().x())).replace("%%distance%%",str(widthm/1000))+curquery[curquery.rfind('}')+1:]
        self.dlg.inp_sparql.setPlainText(curquery)

    def getPointFromCanvas(self):
        self.d = QDialog()
        self.vl = QgsVectorLayer("Point", "temporary_points", "memory")
        self.map_canvas = QgsMapCanvas(self.d)
        self.map_canvas.setMinimumSize(500, 475)
        uri="url=http://a.tile.openstreetmap.org/{z}/{x}/{y}.png&zmin=0&type=xyz"
        self.mts_layer=QgsRasterLayer(uri,'OSM','wms')
        if not self.mts_layer.isValid():
            print ("Layer failed to load!")
        self.rect_tool = RectangleMapTool(self.map_canvas)
        self.map_canvas.setMapTool(self.rect_tool)
        self.map_canvas.setExtent(self.mts_layer.extent())
        self.map_canvas.setLayers( [self.vl,self.mts_layer] )
        self.map_canvas.setCurrentLayer(self.mts_layer)
        chooseLayerLabel=QLabel("Choose Layer Extent:",self.d)
        chooseLayerLabel.move(0,480)	
        self.chooseBBOXLayer=QComboBox(self.d)	
        self.chooseBBOXLayer.move(150,475)	
        b2 = QPushButton("Apply Layer Extent",self.d)	
        b2.move(10,500)	
        b2.clicked.connect(self.setBBOXExtentQuery)	
        layers = QgsProject.instance().layerTreeRoot().children()	
        for layer in layers:	
            self.chooseBBOXLayer.addItem(layer.name())  	
        b1 = QPushButton("Apply BBOX",self.d)
        b1.move(400,500)
        b1.clicked.connect(self.setBBOXInQuery)
        self.d.setWindowTitle("Choose BoundingBox")
        self.d.exec_()

    def saveTripleStoreConfig(self):
        __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
        with open(os.path.join(__location__, 'triplestoreconf_personal.json'),'w') as myfile:
            myfile.write(json.dumps(self.triplestoreconf,indent=2))

    def resetTripleStoreConfig(self):
        __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
        with open(os.path.join(__location__, 'triplestoreconf.json'),'r') as myfile:
               data=myfile.read()
        self.triplestoreconf = json.loads(data)
        with open(os.path.join(__location__, 'triplestoreconf_personal.json'),'w') as myfile:
            myfile.write(json.dumps(self.triplestoreconf,indent=2))

    def viewselectaction(self):
        endpointIndex = self.dlg.comboBox.currentIndex()
        if endpointIndex==0:
            self.justloadingfromfile=False
            return
        if self.dlg.layerconcepts.currentText()!=None and "(Q" in self.dlg.layerconcepts.currentText():
            self.dlg.inp_label.setText(self.dlg.layerconcepts.currentText().split("(")[0].lower().replace(" ","_"))
            concept=self.dlg.layerconcepts.currentText().split("Q")[1].replace(")","")
        else:
            concept=self.dlg.layerconcepts.currentText()
        if "querytemplate" in self.triplestoreconf[endpointIndex]:
            self.dlg.inp_sparql.setPlainText(self.triplestoreconf[endpointIndex]["querytemplate"][self.dlg.queryTemplates.currentIndex()]["query"].replace("%%concept%%",concept))
            if "wd:Q ." in self.dlg.inp_sparql.toPlainText():
                self.dlg.inp_sparql.setPlainText(self.dlg.inp_sparql.toPlainText().replace("wd:Q .", "wd:Q1248784 ."))
        if "#" in self.dlg.layerconcepts.currentText():
            self.dlg.inp_label.setText(self.dlg.layerconcepts.currentText()[self.dlg.layerconcepts.currentText().rfind('#')+1:].lower().replace(" ","_"))
        else:
            self.dlg.inp_label.setText(self.dlg.layerconcepts.currentText()[self.dlg.layerconcepts.currentText().rfind('/')+1:].lower().replace(" ","_"))

    def run(self):
        """Run method that performs all the real work"""
        #try:
        #    print(sparql = SPARQLWrapper("http://dbpedia.org/sparql"))
        #except ImportError as error:
            # Output expected ImportErrors.
        #    print(error.__class__.__name__ + ": " + error.message)
        #except Exception as exception:
            # Output unexpected Exceptions.
        #    print(exception, False)
        #    print(exception.__class__.__name__ + ": " + exception.message)
        # Create the dialog with elements (after translation) and keep reference
        # Only create GUI ONCE in callback, so that it will only load when the plugin is started
        if self.first_start == True:
            __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
            if os.path.isfile(os.path.join(__location__, 'triplestoreconf_personal.json')):
                with open(os.path.join(__location__, 'triplestoreconf_personal.json'),'r') as myfile:
                    data=myfile.read()
            else:
                with open(os.path.join(__location__, 'triplestoreconf.json'),'r') as myfile:
                    data=myfile.read()
            # parse file 
            self.triplestoreconf = json.loads(data)
            self.saveTripleStoreConfig()
            self.first_start = False
            self.dlg = SPAQLunicornDialog()
            #self.dlg.inp_sparql.hide()
            #self.dlg.inp_sparql2=ToolTipPlainText(self.dlg.tab)
            #self.dlg.inp_sparql2.move(10,130)
            #self.dlg.inp_sparql2.setMinimumSize(941,401)
            #self.dlg.inp_sparql2.document().defaultFont().setPointSize(16)
            #self.dlg.inp_sparql2.setPlainText("SELECT ?item ?lat ?lon WHERE {\n ?item ?b ?c .\n ?item <http://www.wikidata.org/prop:P123> ?def .\n}")
            self.sparqlhighlight = SPARQLHighlighter(self.dlg.inp_sparql,self.dlg.errorLabel)
            self.dlg.comboBox.clear()
            for triplestore in self.triplestoreconf:
                if triplestore["active"]:
                    item=triplestore["name"]
                    if "mandatoryvariables" in triplestore:
                        item+=" --> "
                        for mandvar in triplestore["mandatoryvariables"]:
                            item+="?"+mandvar+" "
                        item+=" required!"
                    self.dlg.comboBox.addItem(item)
            self.dlg.comboBox.setCurrentIndex(1)
            self.viewselectaction()
            self.dlg.areaconcepts.hide()
            self.dlg.areas.hide()
            self.dlg.label_8.hide()
            self.dlg.label_9.hide()
            self.dlg.tabWidget.removeTab(2)
            self.dlg.tabWidget.removeTab(1)
            self.dlg.comboBox.currentIndexChanged.connect(self.endpointselectaction)
            self.dlg.queryTemplates.currentIndexChanged.connect(self.viewselectaction)
            self.dlg.loadedLayers.clear()
            self.dlg.inp_sparql.textChanged.connect(self.validateSPARQL)
            self.dlg.bboxButton.clicked.connect(self.getPointFromCanvas)
            self.dlg.addEnrichedLayerButton.clicked.connect(self.addEnrichedLayer)
            self.dlg.interlinkTable.cellClicked.connect(self.createInterlinkSearchDialog)
            self.dlg.enrichTable.cellClicked.connect(self.createEnrichSearchDialog)
            self.dlg.chooseLayerInterlink.clear()
            self.dlg.layerconcepts.clear()
            self.dlg.layerconcepts.setEditable(True)
            self.dlg.layerconcepts.setInsertPolicy(QComboBox.NoInsert)
            self.dlg.searchClass.clicked.connect(self.createInterlinkSearchDialog)
            urlregex = QRegExp("http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+")
            urlvalidator = QRegExpValidator(urlregex, self.dlg)
            self.dlg.interlinkNameSpace.setValidator(urlvalidator)
            self.dlg.interlinkNameSpace.textChanged.connect(self.check_state3)
            self.dlg.interlinkNameSpace.textChanged.emit(self.dlg.interlinkNameSpace.text())
            #self.dlg.layerconcepts.view().setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
            self.dlg.addEnrichedLayerRowButton.clicked.connect(self.addEnrichRow)
            self.dlg.startEnrichment.clicked.connect(self.enrichLayer)
            self.dlg.layerconcepts.currentIndexChanged.connect(self.viewselectaction)
            self.dlg.layerconcepts.currentIndexChanged.connect(self.loadAreas)
            self.dlg.pushButton.clicked.connect(self.create_unicorn_layer) # load action
            self.dlg.exportLayers.clicked.connect(self.exportLayer)
            self.dlg.exportInterlink.clicked.connect(self.exportEnrichedLayer)
            self.dlg.loadLayerInterlink.clicked.connect(self.loadLayerForInterlink)
            self.dlg.enrichTableResult.hide()
            self.dlg.loadTripleStoreButton.clicked.connect(self.buildCustomTripleStoreDialog)
            #self.dlg.loadLayerInterlink.view().setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
            #self.dlg.IDColumnEnrich.view().setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
            self.dlg.loadLayerEnrich.clicked.connect(self.loadLayerForEnrichment)
            #self.dlg.loadLayerEnrich.view().setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
            self.dlg.refreshLayersInterlink.clicked.connect(self.loadUnicornLayers)
            self.dlg.loadFileButton.clicked.connect(self.loadGraph) # load action

        if self.first_start == False:
            self.loadUnicornLayers()

        # show the dialog
        self.dlg.show()
        # Run the dialog event loop
        result = self.dlg.exec_()
        # See if OK was pressed
        if result:
            # Do something useful here - delete the line containing pass and
            # substitute with your code.
            pass
