# -*- coding: latin1 -*-
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
import os, math, time

class Transint(QObject):    

    def __init__(self, iface):
        QObject.__init__(self)
        
        self.settings = QSettings("CatAIS","helmert2d")
        self.outputdir = self.settings.value("outputdir")        
        
        self.iface = iface
        
        self.vlayer = None
        
        self.transformLayer = False
        self.interpolateLayer = False
        
        self.transformationParameters = None
        self.a = None
        self.b = None
        self.c = None
        self.d = None
        self.e = None
        self.f = None

        self.interpolator = None
        self.controlpoints = None
        
        self.transformationMethod = None
        self.interpolationMethod = 1
        self.weightingPower = 1
        self.searchRadius = 0
        self.maxPoints = 0
        self.minPoints = 0
        
        
    def setVectorLayer(self, vlayer):
        self.vlayer = vlayer
        
    
    def transform(self, transformationParameters):
        self.transformLayer = True
        self.transformationParameters = transformationParameters
        
        self.a = float(transformationParameters[0])
        self.b = float(transformationParameters[1])
        self.c = float(transformationParameters[2])
        self.d = float(transformationParameters[3])
        
        if self.e == None and self.f == None:
            self.transformationMethod = 1
        else:
            self.transformationMethod = 2
            self.e = float(transformationParameters[4])
            self.f = float(transformationParameters[5])
            

    def interpolate(self, controlpoins):
        self.interpolateLayer = True
        self.controlpoints = controlpoins

    
    def setInterpolationMethod(self, method):
        self.interpolationMethod = method


    def setWeightingPower(self, power):
        self.weightingPower = power
        
    
    def setSearchRadius(self, radius):
        self.searchRadius = radius
        
        
    def setMaxPoints(self, maxpnts):
        self.maxPoints = maxpnts
        
        
    def setMinPoints(self, minpnts):
        self.minPoints = minpnts
        

    def run(self, addLayerToMap):
        # Check if the output directory is set.
        if self.outputdir == None:
            QMessageBox.warning( None, "helmert2d", "No output directory set.")
            return
            
        # Create a instance of the specific interpolation method.
        if self.interpolateLayer == True:
            if self.interpolationMethod == 1:
                from helmert2d.tools.interpolation.inversedistanceinterpolation import InverseDistanceInterpolation
                self.interpolator = InverseDistanceInterpolation(self.controlpoints, self.weightingPower, self.searchRadius, self.maxPoints, self.minPoints, self.transformLayer)
            else:
                QMessageBox.information(None, 'helmert2d', str("Interpolation method not yet implemented."))   
                return
         
        # Get the layer provider and create a output writer.
        srs = self.iface.mapCanvas().mapRenderer().destinationCrs()

        provider = self.vlayer.dataProvider()
        allAttrs = provider.attributeIndexes()
        provider.select(allAttrs)

        vtype = self.vlayer.wkbType()
        if vtype == QGis.WKBUnknown:
            QMessageBox.information(None, 'helmert2d', str("Unknown geometry type. Data will not be transformed."))   
            return

        time = QDateTime.currentDateTime()
        fileSuffix = str(time.toString(Qt.ISODate)).replace(":", "").replace("-", "")
        filePath = os.path.join(str(self.outputdir.toString()), str(self.vlayer.name()) + str("_processed") + fileSuffix + str(".shp"))
        writer = QgsVectorFileWriter(filePath, "CP1250", provider.fields(), vtype, srs)  

        if writer.hasError() != QgsVectorFileWriter.NoError:
            print "Error when creating shapefile: ", writer.hasError()
            QMessageBox.information(None, 'helmert2d', str("Error when creating shapefile."))   
            return

        # Transform/interpolate the feature.
        QApplication.setOverrideCursor(Qt.WaitCursor)
        try:
            f = QgsFeature()
            while provider.nextFeature(f):   
                g = f.geometry()            
                feat = QgsFeature()
                
                geom = self.processGeometry(g, vtype)
                if geom == None:
                    continue
                
                feat.setGeometry(geom)
                feat.setAttributeMap(f.attributeMap())
                writer.addFeature(feat)
        except:
            QApplication.restoreOverrideCursor()            
        QApplication.restoreOverrideCursor()
            
        del writer
    
        if addLayerToMap == True:
            nvlayer = QgsVectorLayer(filePath, str(self.vlayer.name()) + str("_processed") + fileSuffix, "ogr")                
        
            if not nvlayer.isValid():
                QMessageBox.warning( None, "Helmert2d", "Layer could not be added." )            
                print "Layer failed to load!"
                return
            else:
                QgsMapLayerRegistry.instance().addMapLayer(nvlayer)
        else:
            QMessageBox.warning( None, "Helmert2d", "Layer created: <br><br><i>" + filePath + "</i>" )            



    def processGeometry(self, g, vtype):
        if vtype == QGis.WKBPoint or vtype == QGis.WKBPoint25D:
            p = self.processPoint(g.asPoint())
            if p == None:
                return None
            return QgsGeometry().fromPoint(p)

        elif vtype == QGis.WKBLineString or vtype == QGis.WKBLineString25D:
            coords = g.asPolyline()
            coords_transformed = []
            for i in coords:
                p = self.processPoint(i)
                if p == None:
                    return None
                coords_transformed.append(p)
            return QgsGeometry().fromPolyline(coords_transformed)
        
        elif vtype == QGis.WKBPolygon or vtype == QGis.WKBPolygon25D:
            coords = g.asPolygon()
            coords_transformed = []
            ring = []
            for i in coords:
                for k in i: 
                    p = self.processPoint(k)
                    if p == None:
                        return None
                    ring.append(p)
                coords_transformed .append(ring)
                ring = []
            return QgsGeometry().fromPolygon(coords_transformed )
                
        elif vtype == QGis.WKBMultiPoint or vtype == QGis.WKBMultiPoint25D:
            coords = g.asMultiPoint()
            coords_transformed = []
            for i in coords:
                p = self.processPoint(i)
                if p == None:
                    return None                
                coords_transformed.append(p)
            return QgsGeometry().fromMultiPoint(coords_transformed)
            
        elif vtype == QGis.WKBMultiLineString or vtype == QGis.WKBMultiLineString25D:
            coords = g.asMultiPolyline()
            coords_transformed = []
            singleline = [] 
            for i in coords:
                for j in i:
                    p = self.processPoint(j)
                    if p == None:
                        return None
                    singleline.append(p)
                coords_transformed.append(singleline)
                singleline = []
            return QgsGeometry().fromMultiPolyline(coords_transformed)
                
        elif vtype == QGis.WKBMultiPolygon or vtype == QGis.WKBMultiPolygon25D:
            coords = g.asMultiPolygon()
            coords_transformed = []
            ring = []
            for i in coords:
                for j in i:
                    for k in j:
                        p = self.processPoint(k)
                        if p == None:
                            return None
                        ring.append(p)
                    coords_transformed.append(ring)
                    ring = []
            return QgsGeometry().fromMultiPolygon([coords_transformed])
            
        else:
            QMessageBox.information(None, 'helmert2d', str("Should not reach here..."))  
            return None


    def processPoint(self, point):
        p = QgsPoint()
        
        if self.transformLayer == True:
            if self.transformationMethod == 1:
                x = self.a + self.c*point.x() - self.d*point.y()
                y = self.b + self.d*point.x() + self.c*point.y()
            elif self.transformationMethod == 2:
                x = self.a + self.c*point.x() - self.d*point.y()
                y = self.b + self.d*point.x() + self.f*point.y()
            p.setX(x)
            p.setY(y)
        else:
            p.setX(point.x())
            p.setY(point.y())
            
        if self.interpolateLayer == True:
            pi = self.interpolator.run(p)
            p.setX(pi.x())
            p.setY(pi.y())
            
        return p
        

