# -*- coding: utf-8 -*-

"""
***************************************************************************
    GdalTools_utils.py
    ---------------------
    Date                 : June 2010
    Copyright            : (C) 2010 by Giuseppe Sucameli
    Email                : brush dot tyler at gmail dot com
***************************************************************************
*                                                                         *
*   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.                                   *
*                                                                         *
***************************************************************************
"""
from builtins import filter
from builtins import map
from builtins import str
from builtins import range
from builtins import object

__author__ = 'Giuseppe Sucameli'
__date__ = 'June 2010'
__copyright__ = '(C) 2010, Giuseppe Sucameli'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

# Utility functions
# -------------------------------------------------
# getLastUsedDir()
# setLastUsedDir( QString *file_or_dir path )
# -------------------------------------------------

from qgis.PyQt.QtCore import QObject, QSettings, QFileInfo, QDir, QCoreApplication, pyqtSignal
from qgis.PyQt.QtWidgets import QFileDialog

from qgis.core import QgsApplication, QgsRectangle, QgsProviderRegistry, QgsLogger, QgsProject
from qgis.gui import QgsEncodingFileDialog

from osgeo import gdal, ogr, osr

import os
# to know the os
import platform
import sys
import string
import re

# Escapes arguments and return them joined in a string


def escapeAndJoin(strList):
    joined = ''
    for s in strList:
        if s.find(" ") is not -1:
            escaped = '"' + s.replace('\\', '\\\\').replace('"', '\\"') + '"'
        else:
            escaped = s
        joined += escaped + " "
    return joined.strip()

# Retrieves last used dir from persistent settings


def getLastUsedDir():
    settings = QSettings()
    lastProjectDir = settings.value("/UI/lastProjectDir", u".", type=str)
    return settings.value("/GdalTools/lastUsedDir", lastProjectDir, type=str)

# Stores last used dir in persistent settings


def setLastUsedDir(filePath):
    settings = QSettings()
    fileInfo = QFileInfo(filePath)
    if fileInfo.isDir():
        dirPath = fileInfo.filePath()
    else:
        dirPath = fileInfo.path()
    settings.setValue("/GdalTools/lastUsedDir", dirPath)

# Retrieves GDAL binaries location


def getGdalBinPath():
    settings = QSettings()
    return settings.value("/GdalTools/gdalPath", u"", type=str)

# Stores GDAL binaries location


def setGdalBinPath(path):
    settings = QSettings()
    settings.setValue("/GdalTools/gdalPath", path)

# Retrieves GDAL python modules location


def getGdalPymodPath():
    settings = QSettings()
    return settings.value("/GdalTools/gdalPymodPath", u"", type=str)

# Stores GDAL python modules location


def setGdalPymodPath(path):
    settings = QSettings()
    settings.setValue("/GdalTools/gdalPymodPath", path)

# Retrieves GDAL help files location


def getHelpPath():
    settings = QSettings()
    return settings.value("/GdalTools/helpPath", u"", type=str)

# Stores GDAL help files location


def setHelpPath(path):
    settings = QSettings()
    settings.setValue("/GdalTools/helpPath", path)

# Retrieves last used encoding from persistent settings


def getLastUsedEncoding():
    settings = QSettings()
    return settings.value("/UI/encoding", u"System", type=str)

# Stores last used encoding in persistent settings


def setLastUsedEncoding(encoding):
    settings = QSettings()
    settings.setValue("/UI/encoding", encoding)


def getRasterExtensions():
    formats = FileFilter.allRastersFilter().split(";;")
    extensions = []
    for f in formats:
        if string.find(f, "*.bt") is not -1 or string.find(f, "*.mpr") is not -1:   # Binary Terrain or ILWIS
            continue
        extensions.extend(FileFilter.getFilterExtensions(f))
    return extensions


def getVectorExtensions():
    formats = FileFilter.allVectorsFilter().split(";;")
    extensions = []
    for f in formats:
        extensions.extend(FileFilter.getFilterExtensions(f))
    return extensions


class LayerRegistry(QObject):
    layersChanged = pyqtSignal()

    _instance = None
    _iface = None

    @staticmethod
    def instance():
        if LayerRegistry._instance is None:
            LayerRegistry._instance = LayerRegistry()
        return LayerRegistry._instance

    @staticmethod
    def setIface(iface):
        LayerRegistry._iface = iface

    layers = []

    def __init__(self):
        QObject.__init__(self)
        if LayerRegistry._instance is not None:
            return

        LayerRegistry.layers = self.getAllLayers()
        LayerRegistry._instance = self
        QgsProject.instance().removeAll.connect(self.removeAllLayers)
        QgsProject.instance().layerWasAdded.connect(self.layerAdded)
        QgsProject.instance().layerWillBeRemoved.connect(self.removeLayer)

    def getAllLayers(self):
        return list(node.layer() for node in QgsProject.instance().layerTreeRoot().findLayers())

    def layerAdded(self, layer):
        LayerRegistry.layers.append(layer)
        self.layersChanged.emit()

    def removeLayer(self, layerId):
        LayerRegistry.layers = [x for x in LayerRegistry.layers if x.id() != layerId]
        self.layersChanged.emit()

    def removeAllLayers(self):
        LayerRegistry.layers = []
        self.layersChanged.emit()

    @classmethod
    def isRaster(self, layer):
        # only gdal raster layers
        if layer.type() != layer.RasterLayer:
            return False
        if layer.providerType() != 'gdal':
            return False
        return True

    def getRasterLayers(self):
        return list(filter(self.isRaster, LayerRegistry.layers))

    @classmethod
    def isVector(self, layer):
        if layer.type() != layer.VectorLayer:
            return False
        if layer.providerType() != 'ogr':
            return False
        return True

    def getVectorLayers(self):
        return list(filter(self.isVector, LayerRegistry.layers))


def getRasterFiles(path, recursive=False):
    rasters = []
    if not QFileInfo(path).exists():
        return rasters

    # TODO remove *.aux.xml
    _filter = getRasterExtensions()
    workDir = QDir(path)
    workDir.setFilter(QDir.Files | QDir.NoSymLinks | QDir.NoDotAndDotDot)
    workDir.setNameFilters(_filter)
    files = workDir.entryList()
    for f in files:
        rasters.append(path + "/" + f)

    if recursive:
        for myRoot, myDirs, myFiles in os.walk(str(path)):
            for dir in myDirs:
                workDir = QDir(myRoot + "/" + dir)
                workDir.setFilter(QDir.Files | QDir.NoSymLinks | QDir.NoDotAndDotDot)
                workDir.setNameFilters(_filter)
                workFiles = workDir.entryList()
                for f in workFiles:
                    rasters.append(myRoot + "/" + dir + "/" + f)

    return rasters


def fillRasterOutputFormat(aFilter=None, filename=None):
    shortName = ''

    if aFilter is not None:
        supportedRasters = GdalConfig.getSupportedRasters()
        filterName = re.sub('^.*\] ', '', FileFilter.getFilterName(aFilter))
        if filterName is supportedRasters:
            return supportedRasters[filterName]["SHORTNAME"]

        shortName = GdalConfig.SupportedRasters.long2ShortName(filterName)

    if shortName == '' and filename is not None:
        shortName = GdalConfig.SupportedRasters.filename2ShortName(filename)

    if shortName == '':
        shortName = "GTiff"

    return shortName


def fillVectorOutputFormat(aFilter=None, filename=None):
    shortName = ''

    if aFilter is not None:
        supportedVectors = GdalConfig.getSupportedVectors()
        filterName = re.sub('^.*\] ', '', FileFilter.getFilterName(aFilter))
        if filterName in supportedVectors:
            return supportedVectors[filterName]["SHORTNAME"]

        pass  # shortName = GdalConfig.SupportedVectors.long2ShortName(filterName)

    if shortName == '' and filename is not None:
        pass  # shortName = GdalConfig.SupportedVectors.filename2ShortName(filename)

    if shortName == '':
        shortName = "ESRI Shapefile"

    return shortName


class UnsupportedOGRFormat(Exception):

    def __init__(self):
        msg = QCoreApplication.translate("GdalTools", "The selected file is not a supported OGR format")
        Exception.__init__(self, msg)


def getVectorFields(vectorFile):
    hds = ogr.Open(str(vectorFile).encode('utf8'))
    if hds is None:
        raise UnsupportedOGRFormat()

    fields = []
    names = []

    layer = hds.GetLayer(0)
    defn = layer.GetLayerDefn()

    for i in range(defn.GetFieldCount()):
        fieldDefn = defn.GetFieldDefn(i)
        fieldType = fieldDefn.GetType()
        if fieldType == 0 or fieldType == 2:
            fields.append(fieldDefn)
            names.append(fieldDefn.GetName())

    return (fields, names)

# get raster SRS if possible


def getRasterSRS(parent, fileName):
    ds = gdal.Open(fileName)
    if ds is None:
        return ''

    proj = ds.GetProjectionRef()
    if proj is None:
        return ''

    sr = osr.SpatialReference()
    if sr.ImportFromWkt(proj) != gdal.CE_None:
        return ''

    name = sr.GetAuthorityName(None)
    code = sr.GetAuthorityCode(None)
    if name is not None and code is not None:
        return '%s:%s' % (name, code)

    return ''

# get raster extent using python API - replaces old method which parsed gdalinfo output


def getRasterExtent(parent, fileName):
    ds = gdal.Open(fileName)
    if ds is None:
        return

    x = ds.RasterXSize
    y = ds.RasterYSize

    gt = ds.GetGeoTransform()
    if gt is None:
        xUL = 0
        yUL = 0
        xLR = x
        yLR = y
    else:
        xUL = gt[0]
        yUL = gt[3]
        xLR = gt[0] + gt[1] * x + gt[2] * y
        yLR = gt[3] + gt[4] * x + gt[5] * y

    return QgsRectangle(xUL, yLR, xLR, yUL)


# get raster resolution

def getRasterResolution(fileName):
    ds = gdal.Open(fileName)
    if ds is None:
        return

    gt = ds.GetGeoTransform()

    if gt is None:
        return
    else:
        xRes = abs(gt[1])
        yRes = abs(gt[5])
        return (xRes, yRes)

# This class is used to replace the QFileDialog class.
# Its static methods are used in place of the respective QFileDialog ones to:
# 1. set the last used directory
# 2. append the selected extension to the file name
# 3. bypass the following bug:
# when you use the 'filter' argument, the dialog is enlarged up to the longest filter length,
# so sometimes the dialog excedes the screen width


class FileDialog(object):

    @classmethod
    def getDialog(self, parent=None, caption='', acceptMode=QFileDialog.AcceptOpen, fileMode=QFileDialog.ExistingFile, filter='', selectedFilter=None, useEncoding=False):
        if useEncoding:
            dialog = QgsEncodingFileDialog(parent, caption, getLastUsedDir(), filter, getLastUsedEncoding())
        else:
            dialog = QFileDialog(parent, caption, getLastUsedDir(), filter)
        dialog.setFileMode(fileMode)
        dialog.setAcceptMode(acceptMode)

        if selectedFilter is not None:
            dialog.selectNameFilter(selectedFilter[0])

        if not dialog.exec_():
            if useEncoding:
                return ('', None)
            return ''

        # change the selected filter value
        if selectedFilter is not None:
            selectedFilter[0] = dialog.selectedNameFilter()

        # save the last used dir and return the selected files
        files = dialog.selectedFiles()
        if files != '':
            setLastUsedDir(files[0])

            if fileMode != QFileDialog.ExistingFiles:
                files = files[0]
                # append the extension if not already present
                if fileMode == QFileDialog.AnyFile:
                    firstExt = None
                    for ext in FileFilter.getFilterExtensions(dialog.selectedNameFilter()):
                        if FileFilter.filenameMatchesFilterExt(files, ext):
                            firstExt = None
                            break

                        if firstExt is None:
                            firstExt = ext

                    if firstExt is not None:
                        if firstExt.startswith('*'):
                            files += firstExt[1:]

        if useEncoding:
            encoding = dialog.encoding()
            # encoding setted yet by QgsEncodingFileDialog
            #setLastUsedEncoding(encoding)
            return (files, encoding)

        return files

    @classmethod
    def getOpenFileNames(self, parent=None, caption='', filter='', selectedFilter=None, useEncoding=False):
        if useEncoding:
            return self.getDialog(parent, caption, QFileDialog.AcceptOpen, QFileDialog.ExistingFiles, filter, selectedFilter, useEncoding)
        res, selected_filter = QFileDialog.getOpenFileNames(parent, caption, getLastUsedDir(), filter)
        if len(res) > 0:
            setLastUsedDir(res[-1])
        return res

    @classmethod
    def getOpenFileName(self, parent=None, caption='', filter='', selectedFilter=None, useEncoding=False):
        if useEncoding:
            return self.getDialog(parent, caption, QFileDialog.AcceptOpen, QFileDialog.ExistingFile, filter, selectedFilter, useEncoding)
        res, selected_filter = QFileDialog.getOpenFileName(parent, caption, getLastUsedDir(), filter)
        if res:
            setLastUsedDir(res)
        return res

    @classmethod
    def getSaveFileName(self, parent=None, caption='', filter='', selectedFilter=None, useEncoding=False):
        if useEncoding:
            return self.getDialog(parent, caption, QFileDialog.AcceptSave, QFileDialog.AnyFile, filter, selectedFilter, useEncoding)
        res, filter = QFileDialog.getSaveFileName(parent, caption, getLastUsedDir(), filter)
        if res:
            setLastUsedDir(res)
        return res

    @classmethod
    def getExistingDirectory(self, parent=None, caption='', useEncoding=False):
        if useEncoding:
            return self.getDialog(parent, caption, QFileDialog.AcceptOpen, QFileDialog.DirectoryOnly, '', None, useEncoding)
        res = QFileDialog.getExistingDirectory(parent, caption, getLastUsedDir(), QFileDialog.ShowDirsOnly)
        if res:
            setLastUsedDir(res)
        return res


class FileFilter(object):

    @classmethod
    def getFilter(self, typeName):
        settings = QSettings()
        return settings.value("/GdalTools/" + typeName + "FileFilter", u"", type=str)

    @classmethod
    def setFilter(self, typeName, aFilter):
        settings = QSettings()
        settings.setValue("/GdalTools/" + typeName + "FileFilter", aFilter)

    # stores the supported raster file filter
    rastersFilter = ''

    # Retrieves the filter for supported raster files
    @classmethod
    def allRastersFilter(self):
        if self.rastersFilter == '':
            self.rastersFilter = QgsProviderRegistry.instance().fileRasterFilters()

            # workaround for Qgis < 1.5 (see #2376)
            # removed as this is a core plugin Qgis >= 1.9

        return self.rastersFilter

    # Retrieves the filter for supported raster files to save
    # Skip *, *.zip and *.vrt and move tif to top
    # TODO: only the formats with GDAL_DCAP_CREATE
    @classmethod
    def saveRastersFilter(self):
        # move tif to top if available
        available = self.allRastersFilter().split(";;")

        filters = []

        for f in available:
            if "*.tif" in f:
                filters.append(f)
                break

        for f in available:
            if "*.tif" in f or "*.zip" in f or "(*)" in f:
                continue

            filters.append(f)

        return ";;".join(filters)

    # Retrieves the last used filter for raster files
    # Note: filter string is in a list
    @classmethod
    def lastUsedRasterFilter(self):
        return [self.getFilter("lastRaster")]

    @classmethod
    def setLastUsedRasterFilter(self, aFilter):
        self.setFilter("lastRaster", aFilter[0])

    # stores the supported vectors file filter
    vectorsFilter = ''

    # Retrieves the filter for supported vector files
    @classmethod
    def allVectorsFilter(self):
        if self.vectorsFilter == '':
            self.vectorsFilter = QgsProviderRegistry.instance().fileVectorFilters()
        return self.vectorsFilter

    # Retrieves the last used filter for vector files
    # Note: filter string is in a list
    @classmethod
    def lastUsedVectorFilter(self):
        return [self.getFilter("lastVector")]

    @classmethod
    def setLastUsedVectorFilter(self, aFilter):
        self.setFilter("lastVector", aFilter[0])

    # Retrieves the extensions list from a filter string
    @classmethod
    def getFilterExtensions(self, aFilter):
        extList = []
        # foreach format in filter string
        for f in aFilter.split(";;"):
            # gets the list of extensions from the filter
            exts = re.sub('\).*$', '', re.sub('^.*\(', '', f))
            # if there is no extensions or the filter matches all, then return an empty list
            # otherwise return the list of estensions
            if exts != '' and exts != "*" and exts != "*.*":
                extList.extend(exts.split(" "))
        return extList

    @classmethod
    def getFilterName(self, aFilter):
        if isinstance(aFilter, list):
            if len(aFilter):
                aFilter = aFilter[0]
            else:
                aFilter = ""
        return string.strip(re.sub('\ \(.*$', '', aFilter))

    @classmethod
    def filenameMatchesFilterExt(self, fileName, ext):
        return re.match('.' + str(ext), fileName) is not None

# Retrieves gdal information


class GdalConfig(object):
    # retrieves and return the installed gdal version

    @classmethod
    def version(self):
        return Version(gdal.VersionInfo("RELEASE_NAME"))

    @classmethod
    def versionNum(self):
        return int(gdal.VersionInfo("VERSION_NUM"))

    # store the supported rasters info
    supportedRasters = None

    # retrieve the supported rasters info
    @classmethod
    def getSupportedRasters(self):
        if self.supportedRasters is not None:
            return self.supportedRasters

        # first get the GDAL driver manager
        if gdal.GetDriverCount() == 0:
            gdal.AllRegister()

        self.supportedRasters = dict()
        jp2Driver = None

        # for each loaded GDAL driver
        for i in range(gdal.GetDriverCount()):
            driver = gdal.GetDriver(i)

            if driver is None:
                QgsLogger.warning("unable to get driver " + str(i))
                continue

            # now we need to see if the driver is for something currently
            # supported; if not, we give it a miss for the next driver

            longName = string.strip(re.sub('\(.*$', '', driver.LongName))
            shortName = string.strip(re.sub('\(.*$', '', driver.ShortName))
            extensions = ''

            description = driver.GetDescription()
            glob = []

            metadata = driver.GetMetadata()
            if gdal.DMD_EXTENSION in metadata:
                extensions = str(metadata[gdal.DMD_EXTENSION])

            if longName != '':
                if extensions != '':
                    # XXX add check for SDTS; in that case we want (*CATD.DDF)

                    #TODO fix and test
                    #glob.append( QString("*." + extensions.replace("/", " *.")).split(" "))
                    glob.append(string.split("*." + string.replace(extensions, "/", " *."), sep=(" ")))

                    # Add only the first JP2 driver found to the filter list (it's the one GDAL uses)
                    if description == "JPEG2000" or description.startswith("JP2"):  # JP2ECW, JP2KAK, JP2MrSID
                        if jp2Driver is not None:
                            continue               # skip if already found a JP2 driver
                        jp2Driver = driver   # first JP2 driver found
                        glob.append("*.j2k")           # add alternate extension
                    elif description == "GTiff":
                        glob.append("*.tiff")
                    elif description == "JPEG":
                        glob.append("*.jpeg")
                else:
                    # USGS DEMs use "*.dem"
                    if description.startswith("USGSDEM"):
                        glob.append("*.dem")
                    elif description.startswith("DTED"):
                        # DTED use "*.dt0"
                        glob.append("*.dt0")
                    elif description.startswith("MrSID"):
                        # MrSID use "*.sid"
                        glob.append("*.sid")
                    else:
                        continue

                self.supportedRasters[longName] = {'EXTENSIONS': glob, 'LONGNAME': longName, 'SHORTNAME': shortName, 'DESCRIPTION': description}

        return self.supportedRasters

    # store the supported vectors info
    supportedVectors = None

    # retrieve the supported vectors info
    @classmethod
    def getSupportedVectors(self):
        if self.supportedVectors is not None:
            return self.supportedVectors

        # first get the OGR driver manager
        QgsApplication.registerOgrDrivers()

        self.supportedVectors = dict()

        # for each loaded OGR driver
        for i in range(ogr.GetDriverCount()):
            driver = ogr.GetDriver(i)

            if driver is None:
                QgsLogger.warning("unable to get driver " + str(i))
                continue

            driverName = driver.GetName()
            longName = ''
            glob = []

            if driverName.startswith("AVCBin"):
                pass  # myDirectoryDrivers += "Arc/Info Binary Coverage,AVCBin"
            elif driverName.startswith("AVCE00"):
                longName = "Arc/Info ASCII Coverage"
                glob.append("*.e00")
            elif driverName.startswith("BNA"):
                longName = "Atlas BNA"
                glob.append("*.bna")
            elif driverName.startswith("CSV"):
                longName = "Comma Separated Value"
                glob.append("*.csv")
            elif driverName.startswith("DODS"):
                pass  # myProtocolDrivers += "DODS/OPeNDAP,DODS"
            elif driverName.startswith("PGeo"):
                pass  # myDatabaseDrivers += "ESRI Personal GeoDatabase,PGeo"

                # on Windows add a pair to the dict for this driver
                if platform.system() == "Windows":
                    longName = "ESRI Personal GeoDatabase"
                    glob.append("*.mdb")
            elif driverName.startswith("SDE"):
                pass  # myDatabaseDrivers += "ESRI ArcSDE,SDE"
            elif driverName.startswith("ESRI"):
                longName = "ESRI Shapefiles"
                glob.append("*.shp")
            elif driverName.startswith("FMEObjects Gateway"):
                longName = "FMEObjects Gateway"
                glob.append("*.fdd")
            elif driverName.startswith("GeoJSON"):
                pass  # myProtocolDrivers += "GeoJSON,GeoJSON"
                longName = "GeoJSON"
                glob.append("*.geojson")
            elif driverName.startswith("GeoRSS"):
                longName = "GeoRSS"
                glob.append("*.xml")
            elif driverName.startswith("GML"):
                longName = "Geography Markup Language"
                glob.append("*.gml")
            elif driverName.startswith("GMT"):
                longName = "GMT"
                glob.append("*.gmt")
            elif driverName.startswith("GPX"):
                longName = "GPX"
                glob.append("*.gpx")
            elif driverName.startswith("GRASS"):
                pass  # myDirectoryDrivers += "Grass Vector,GRASS"
            elif driverName.startswith("IDB"):
                pass  # myDatabaseDrivers += "Informix DataBlade,IDB"
            elif driverName.startswith("Interlis 1"):
                longName = "INTERLIS 1"
                glob.append("*.itf")
                glob.append("*.xml")
                glob.append("*.ili")
            elif driverName.startswith("Interlis 2"):
                longName = "INTERLIS 2"
                glob.append("*.itf")
                glob.append("*.xml")
                glob.append("*.ili")
            elif driverName.startswith("INGRES"):
                pass  # myDatabaseDrivers += "INGRES,INGRES"
            elif driverName.startswith("KML"):
                longName = "KML"
                glob.append("*.kml")
            elif driverName.startswith("MapInfo File"):
                longName = "Mapinfo File"
                glob.append("*.mif")
                glob.append("*.tab")
            elif driverName.startswith("DGN"):
                longName = "Microstation DGN"
                glob.append("*.dgn")
            elif driverName.startswith("MySQL"):
                pass  # myDatabaseDrivers += "MySQL,MySQL"
            elif driverName.startswith("OCI"):
                pass  # myDatabaseDrivers += "Oracle Spatial,OCI"
            elif driverName.startswith("ODBC"):
                pass  # myDatabaseDrivers += "ODBC,ODBC"
            elif driverName.startswith("OGDI"):
                pass  # myDatabaseDrivers += "OGDI Vectors,OGDI"
            elif driverName.startswith("PostgreSQL"):
                pass  # myDatabaseDrivers += "PostgreSQL,PostgreSQL"
            elif driverName.startswith("S57"):
                longName = "S-57 Base file"
                glob.append("*.000")
            elif driverName.startswith("SDTS"):
                longName = "Spatial Data Transfer Standard"
                glob.append("*catd.ddf")
            elif driverName.startswith("SQLite"):
                longName = "SQLite"
                glob.append("*.sqlite")
            elif driverName.startswith("UK .NTF"):
                pass  # myDirectoryDrivers += "UK. NTF,UK. NTF"
            elif driverName.startswith("TIGER"):
                pass  # myDirectoryDrivers += "U.S. Census TIGER/Line,TIGER"
            elif driverName.startswith("VRT"):
                longName = "VRT - Virtual Datasource "
                glob.append("*.vrt")
            elif driverName.startswith("XPlane"):
                longName = "X-Plane/Flighgear"
                glob.append("apt.dat")
                glob.append("nav.dat")
                glob.append("fix.dat")
                glob.append("awy.dat")

            longName = string.strip(longName)

            if longName == '':
                continue

            self.supportedVectors[longName] = {'EXTENSIONS': glob, 'LONGNAME': longName, 'SHORTNAME': driverName}

        return self.supportedVectors

    class SupportedRasters(object):
        dict_long2shortName = dict()

        # retrieve the raster format short name by long format name
        @classmethod
        def long2ShortName(self, longName):
            if longName == '':
                return ''

            if longName in self.dict_long2shortName:
                return self.dict_long2shortName[longName]

            # first get the GDAL driver manager
            if gdal.GetDriverCount() == 0:
                gdal.AllRegister()

            shortName = ''

            # for each loaded GDAL driver
            for i in range(gdal.GetDriverCount()):
                driver = gdal.GetDriver(i)
                if driver is None:
                    continue

                # if this is the driver we searched for then return its short name
                if FileFilter.getFilterName(driver.LongName) == longName:
                    shortName = FileFilter.getFilterName(driver.ShortName)
                    self.dict_long2shortName[longName] = shortName
                    break

            return shortName

        # retrieve the raster format short name by using the file name extension
        @classmethod
        def filename2ShortName(self, fileName):
            if fileName == '':
                return ''

            shortName = ''

            # for each raster format search for the file extension
            formats = FileFilter.allRastersFilter().split(";;")
            for f in formats:
                for ext in FileFilter.getFilterExtensions(f):
                    if FileFilter.filenameMatchesFilterExt(fileName, ext):
                        longName = FileFilter.getFilterName(f)
                        shortName = self.long2ShortName(longName)
                        break

                if not shortName == '':
                    break

            return shortName

# class which allows creating version objects and compare them


class Version(object):

    def __init__(self, ver):
        self.vers = ('0', '0', '0')

        if isinstance(ver, Version):
            self.vers = ver.vers
        elif isinstance(ver, tuple) or isinstance(ver, list):
            self.vers = list(map(str, ver))
        elif isinstance(ver, str):
            self.vers = self.string2vers(ver)

    @staticmethod
    def string2vers(string):
        vers = ['0', '0', '0']

        nums = str(string).split(".")

        if len(nums) > 0:
            vers[0] = nums[0]
        if len(nums) > 1:
            vers[1] = nums[1]
        if len(nums) > 2:
            vers[2] = nums[2]

        return (vers[0], vers[1], vers[2])

    def __cmp__(self, other):
        if not isinstance(other, Version):
            other = Version(other)

        if self.vers > other.vers:
            return 1
        if self.vers < other.vers:
            return -1
        return 0

    def __str__(self):
        return ".".join(self.vers)


def setProcessEnvironment(process):
    envvar_list = {
        "PATH": getGdalBinPath(),
        "PYTHONPATH": getGdalPymodPath(),
        "GDAL_FILENAME_IS_UTF8": "NO"
    }

    sep = os.pathsep

    for name, val in envvar_list.items():
        if val is None or val == "":
            continue

        envval = os.getenv(name)
        if envval is None or envval == "":
            envval = str(val)
        elif (platform.system() == "Windows" and val.lower() not in envval.lower().split(sep)) or \
             (platform.system() != "Windows" and val not in envval.split(sep)):
            envval += "%s%s" % (sep, str(val))
        else:
            envval = None

        if envval is not None:
            os.putenv(name, envval)


def setMacOSXDefaultEnvironment():
    # fix bug #3170: many GDAL Tools don't work in OS X standalone

    if platform.system() != "Darwin":
        return

    # QgsApplication.prefixPath() contains the path to qgis executable (i.e. .../Qgis.app/MacOS)
    # get the path to Qgis application folder
    qgis_app = u"%s/.." % QgsApplication.prefixPath()
    qgis_app = QDir(qgis_app).absolutePath()

    qgis_bin = u"%s/bin" % QgsApplication.prefixPath()   # path to Qgis bin folder
    qgis_python = u"%s/Resources/python" % qgis_app    # path to Qgis python folder

    # path to the GDAL framework within the Qgis application folder (Qgis standalone only)
    qgis_standalone_gdal_path = u"%s/Frameworks/GDAL.framework" % qgis_app

    # path to the GDAL framework when installed as external framework
    gdal_versionsplit = str(GdalConfig.version()).split('.')
    gdal_base_path = u"/Library/Frameworks/GDAL.framework/Versions/%s.%s" % (gdal_versionsplit[0], gdal_versionsplit[1])

    if os.path.exists(qgis_standalone_gdal_path):  # qgis standalone
        # GDAL executables are in the Qgis bin folder
        if getGdalBinPath() == '':
            setGdalBinPath(qgis_bin)
        # GDAL pymods are in the Qgis python folder
        if getGdalPymodPath() == '':
            setGdalPymodPath(qgis_python)
        # GDAL help is in the framework folder
        if getHelpPath() == '':
            setHelpPath(u"%s/Resources/doc" % qgis_standalone_gdal_path)

    elif os.path.exists(gdal_base_path):
        # all GDAL parts are in the GDAL framework folder
        if getGdalBinPath() == '':
            setGdalBinPath(u"%s/Programs" % gdal_base_path)
        if getGdalPymodPath() == '':
            setGdalPymodPath(u"%s/Python/%s.%s/site-packages" % (gdal_base_path, sys.version_info[0], sys.version_info[1]))
        if getHelpPath() == '':
            setHelpPath(u"%s/Resources/doc" % gdal_base_path)


# setup the MacOSX path to both GDAL executables and python modules
if platform.system() == "Darwin":
    setMacOSXDefaultEnvironment()