# -*- 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 )
# -------------------------------------------------

#import os

from qgis.PyQt.QtCore import QObject, QSettings
from qgis.PyQt.QtWidgets import  QFileDialog
import platform
import gdal
from qgis.core import QgsProviderRegistry

#from PyQt4.QtCore import *
#from PyQt4.QtGui import *
#from osgeo import gdal, ogr, osr
#from osgeo.gdalconst import *
#from qgis.core import *
#from qgis.gui import *
# 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):
    _instance = None
    _iface = None

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

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

    layers = []

    def __init__(self):
        QObject.__init__(self)
        if LayerRegistry._instance != 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):
        if LayerRegistry._iface and hasattr(LayerRegistry._iface, 'legendInterface'):
            return LayerRegistry._iface.legendInterface().layers()
        return list(QgsProject.instance().mapLayers().values())

    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 != None:
        supportedRasters = GdalConfig.getSupportedRasters()
        filterName = re.sub('^.*\] ', '', FileFilter.getFilterName(aFilter[0]))
        if filterName in supportedRasters:
            return supportedRasters[filterName]["SHORTNAME"]

        shortName = GdalConfig.SupportedRasters.long2ShortName(filterName)

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

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

    return shortName


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

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

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

    if shortName == '' and filename != 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 == 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)


# 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 == None:
                            firstExt = ext

                    if firstExt != 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):
        return self.getDialog(parent, caption, QFileDialog.AcceptOpen, QFileDialog.ExistingFiles, filter,
                              selectedFilter, useEncoding)

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

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

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


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 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):
        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 != 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 == 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 != 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 != 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 == 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 == 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 == None or val == "":
            continue

        envval = os.getenv(name)
        if envval == 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 != 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()
