
# first qgis
from qgis.core import *
from qgis.gui import *
# next Qt
from PyQt4.QtCore import *
from PyQt4.QtGui import *

from pywps import config
import os
import urllib2
import logging
import tempfile


class QGIS:

    project = None
    projectFileName = None
    outputs = None
    process = None
    sessionId = None

    def __init__(self, process, sessId):

        tmp = os.path.basename(tempfile.mkstemp()[1])
        self.outputs = {}
        self.process = process
        self.sessionId = sessId

        self.project = QgsProject.instance()

        treeRoot = self.project.layerTreeRoot()
        model = QgsLayerTreeModel(treeRoot)
        view = QgsLayerTreeView()
        view.setModel(model)
        self.canvas = QgsMapCanvas()
        self.canvas.setCrsTransformEnabled(True)
        self.bridge = QgsLayerTreeMapCanvasBridge(treeRoot, self.canvas)

        self.project.writeProject.connect(self.bridge.writeProject)
        self.project.writeProject.connect(self.__writeProject__)

        self.projectFileName = os.path.join(config.getConfigValue(
            "server", "outputPath"), self.sessionId + ".qgs")
        if os.path.exists(self.projectFileName):
            self.project.read(QFileInfo(self.projectFileName))
        else:
            self.project.writePath(self.projectFileName)

        self.project.setTitle("%s-%s" %
                              (self.process.identifier, self.sessionId))
        self.project.writeEntry("WMSServiceCapabilities", "/", True)
        self.project.writeEntry("WMSServiceTitle", "/",
                                config.getConfigValue("wps", "title"))
        self.project.writeEntry("WMSServiceAbstract",
                                "/", config.getConfigValue("wps", "abstract"))
        self.project.writeEntry("WMSKeywordList", "/",
                                config.getConfigValue("wps", "keywords"))
        self.project.writeEntry(
            "WMSFees", "/", config.getConfigValue("wps", "fees"))
        self.project.writeEntry(
            "WMSAccessConstraints", "/", config.getConfigValue("wps", "constraints"))
        self.project.writeEntry("WMSContactOrganization", "/",
                                config.getConfigValue("provider", "providerName"))
        self.project.writeEntry(
            "WMSContactPerson", "/", config.getConfigValue("provider", "individualName"))
        self.project.writeEntry("WMSContactPhone", "/",
                                config.getConfigValue("provider", "phoneVoice"))
        self.project.writeEntry(
            "WMSContactPhone", "/", config.getConfigValue("provider", "electronicMailAddress"))

        if config.config.has_section('qgis') and config.config.has_option('qgis', 'output_ows_crss'):
            outputOWSCRSs = config.getConfigValue('qgis', 'output_ows_crss')
            outputOWSCRSs = outputOWSCRSs.split(',')
            outputOWSCRSs = [proj.strip().upper() for proj in outputOWSCRSs]
            self.project.writeEntry("WMSCrsList", "/", outputOWSCRSs)
        else:
            self.project.writeEntry(
                "WMSCrsList", "/", ['EPSG:4326', 'EPSG:3857'])

        self.project.write(QFileInfo(self.projectFileName))

    def __writeProject__(self, doc):
        treeRoot = self.project.layerTreeRoot()
        oldLegendElem = QgsLayerTreeUtils.writeOldLegend(
            doc, treeRoot, False, [])
        doc.firstChildElement("qgis").appendChild(oldLegendElem)

    def getReference(self, output):

        if output.format["mimetype"] in ('text/csv', 'application/x-zipped-shp', 'application/x-zipped-tab'):
            return None

        mlr = QgsMapLayerRegistry.instance()
        logging.info('getReference: ' + output.identifier + ' ' + output.value)
        layersByName = mlr.mapLayersByName(output.identifier)
        outputLayer = None
        if not layersByName:
            outputLayer = QgsRasterLayer(
                output.value, output.identifier, 'gdal')
            if not outputLayer.isValid():
                outputLayer = QgsVectorLayer(
                    output.value, output.identifier, 'ogr')
            mlr.addMapLayer(outputLayer)
        else:
            outputLayer = layersByName[0]

        # Update CRS
        if not outputLayer.dataProvider().crs().authid() and output.projection:
            outputLayer.setCrs(QgsCoordinateReferenceSystem(output.projection))

        treeRoot = self.project.layerTreeRoot()
        if config.config.has_section('qgis') and config.config.has_option('qgis', 'output_ows_crss'):
            outputOWSCRSs = config.getConfigValue('qgis', 'output_ows_crss')
            outputOWSCRSs = outputOWSCRSs.split(',')
            outputOWSCRSs = [proj.strip().upper() for proj in outputOWSCRSs]
            self.canvas.setDestinationCrs(
                QgsCoordinateReferenceSystem(outputOWSCRSs[0]))
        else:
            self.canvas.setDestinationCrs(
                QgsCoordinateReferenceSystem('EPSG:4326'))

        if not treeRoot.findLayer(outputLayer.id()):
            treeRoot.addLayer(outputLayer)

        self.bridge.setCanvasLayers()
        self.canvas.zoomToFullExtent()

        self.project.write(QFileInfo(self.projectFileName))

        if outputLayer.type() == QgsMapLayer.VectorLayer:
            WFSLayers = self.project.readListEntry("WFSLayers", "/")[0]
            if outputLayer.id() not in WFSLayers:
                WFSLayers.append(outputLayer.id())
                self.project.writeEntry("WFSLayers", "/", WFSLayers)
                self.project.write(QFileInfo(self.projectFileName))
            if output.format['mimetype'] in ('application/x-ogc-wms', 'application/x-ogc-wfs'):
                return self.getCapabilities(output)
            return self.getMapServerWFS(output)

        elif outputLayer.type() == QgsMapLayer.RasterLayer:
            output.projection = outputLayer.crs().authid()
            output.height = outputLayer.height()
            output.width = outputLayer.width()
            outputExtent = outputLayer.extent()
            output.bbox = [outputExtent.xMinimum(), outputExtent.yMinimum(
            ), outputExtent.xMaximum(), outputExtent.yMaximum()]
            WCSLayers = self.project.readListEntry("WCSLayers", "/")[0]
            if outputLayer.id() not in WCSLayers:
                WCSLayers.append(outputLayer.id())
                self.project.writeEntry("WCSLayers", "/", WCSLayers)
                self.project.write(QFileInfo(self.projectFileName))
            if output.format['mimetype'] in ('application/x-ogc-wms', 'application/x-ogc-wcs'):
                return self.getCapabilities(output)
            return self.getMapServerWCS(output)

    def getCapabilities(self, output):
        """Get the URL for qgis-server GetCapabilities request of the output"""
        if output.format["mimetype"] == 'application/x-ogc-wms':
            return config.getConfigValue("qgis", "qgisserveraddress") + "?map=" + self.projectFileName + "&SERVICE=WMS" + "&REQUEST=GetCapabilities"
        elif output.format["mimetype"] == 'application/x-ogc-wfs':
            return config.getConfigValue("qgis", "qgisserveraddress") + "?map=" + self.projectFileName + "&SERVICE=WFS" + "&REQUEST=GetCapabilities"
        elif output.format["mimetype"] == 'application/x-ogc-wcs':
            return config.getConfigValue("qgis", "qgisserveraddress") + "?map=" + self.projectFileName + "&SERVICE=WCS" + "&REQUEST=GetCapabilities"
        else:
            return config.getConfigValue("qgis", "qgisserveraddress") + "?map=" + self.projectFileName + "&SERVICE=WMS" + "&REQUEST=GetCapabilities"

    def getMapServerWCS(self, output):
        """Get the URL for qgis-server WCS request of the output"""
        return config.getConfigValue("qgis", "qgisserveraddress") + "?map=" + self.projectFileName + "&SERVICE=WCS" + "&REQUEST=GetCoverage" + "&VERSION=1.0.0" + "&COVERAGE=" + output.identifier + "&CRS=" + output.projection.replace("+init=", "") + ("&BBOX=%s,%s,%s,%s" % (output.bbox[0], output.bbox[1], output.bbox[2], output.bbox[3])) + "&HEIGHT=%s" % (output.height) + ("&WIDTH=%s" % (output.width)) + ("&FORMAT=%s" % output.format["mimetype"])

    def getMapServerWFS(self, output):
        """Get the URL for qgis-server WFS request of the output"""
        url = config.getConfigValue("qgis", "qgisserveraddress") + "?map=" + self.projectFileName + \
            "&SERVICE=WFS" + "&REQUEST=GetFeature" + \
            "&VERSION=1.0.0" + "&TYPENAME=" + output.identifier
        if output.format["mimetype"] == 'application/json':
            url += "&OUTPUTFORMAT=GeoJSON"
        elif output.format["mimetype"] in ('text/xml; subtype=gml/3.1.1', 'application/gml+xml; version=3.1.1'):
            url += "&OUTPUTFORMAT=GML3"
        else:
            url += "&OUTPUTFORMAT=GML2"
        return url
