from PyQt4.QtGui import *
from PyQt4.QtCore import *
from qgis.core import *
from qgis.gui import *

class VectorFixerTool(QgsMapToolEmitPoint):
    def __init__(self,
                 canvas,
                 iface,
                 mapGraphInstance
                ):

        QgsMapToolEmitPoint.__init__(self, canvas)
        self.canvas = canvas
        self.iface = iface
        name = "VectorFixerTool"
        self.tempVectorLayer = None

        self.setObjectName(name)

        self.mapGraph = mapGraphInstance

        self.leftPressed = False
        self.rightPressed = False


        pencilIcon = QImage(":/VectorizeTools/icons/pencil.png").scaled(QSize(32, 32))
        self.pencilCursor = QCursor(QPixmap.fromImage(pencilIcon))
        self.setCursor(self.pencilCursor)


        self.rubberBands = []
        self.rubberBandsBorder = []

        self.rubberBandPointer = QgsRubberBand(self.canvas, QGis.Polygon)
        self.rubberBandPointer.setColor(self.getCorrectColor())
        self.rubberBandPointer.setWidth(1)
        self.rubberBandBorderPointer = QgsRubberBand(self.canvas, QGis.Line)
        self.rubberBandBorderPointer.setColor(QColor(0, 0, 0))
        self.rubberBandBorderPointer.setWidth(1)


    # ========================================= Basic ============================================= #
    def activate(self):
        QgsMapToolEmitPoint.activate(self)
        self.canvas.setFocus()
        self.canvas.refresh()
        self.canvas.repaint()

    def deactivate(self):
        QgsMapToolEmitPoint.deactivate(self)
        self.reset()

    def toolName(self):
        return "VectorizeTool"

    def reset(self):
        self.leftPressed = False
        self.rightPressed = False

        for rb in self.rubberBands:
            rb.reset(QGis.Polygon)
        for rb in self.rubberBandsBorder:
            rb.reset(QGis.Line)

        self.rubberBands = []
        self.rubberBandsBorder = []
        self.rubberBandBorderPointer.reset(QGis.Line)
        self.rubberBandPointer.reset(QGis.Polygon)
        self.rubberBandPointer.setColor(self.getCorrectColor())

    def getSelectedFeature(self):
        lyr = self.iface.activeLayer()
        if lyr and lyr.type() == QgsMapLayer.VectorLayer:
            selected = lyr.selectedFeatures()
            if len(selected) == 1:
                return True, selected[0], lyr
            else:
                QMessageBox.information(None, "", "Please select one feature")
                return False, None, None
        else:
            QMessageBox.information(None, "", "Active layer must be vector")
            return False, None, None

    def canvasPressEvent(self, event):

        if self.getSelectedFeature()[0]:
                self.leftPressed = event.button() == Qt.LeftButton
                self.rightPressed = event.button() == Qt.RightButton

                geomCenter = self.obtainGeomFromEvent(event)

                self.aggiungiNuovoPunto(geomCenter)

    def canvasReleaseEvent(self, event):

        if event.button() == Qt.LeftButton or event.button() == Qt.RightButton:
            self.rubberBandPointer.setColor(self.getCorrectColor())
            self.leftPressed = False
            self.rightPressed = False

            self.chiudiFase(event.button())

    def obtainGeomFromEvent(self, event):
        point = self.canvas.getCoordinateTransform().toMapPoint(event.x(), event.y())
        geomCenter = QgsGeometry.fromRect(self.mapGraph.getPixelRectangleNxN(point))
        geomCenter = geomCenter.smooth(1, 0.25)
        return geomCenter

    def canvasMoveEvent(self, event):
        geomCenter = self.obtainGeomFromEvent(event)

        self.rubberBandPointer.setToGeometry(geomCenter, None)
        self.rubberBandBorderPointer.reset(QGis.Line)
        self.rubberBandBorderPointer.addGeometry(geomCenter, None)

        self.aggiungiNuovoPunto(geomCenter)

    def aggiungiNuovoPunto(self, geomPunto):
        if self.leftPressed or self.rightPressed:
            indiciUniti = []
            geomDaAggiungere = geomPunto
            for ind, puntoR in enumerate(self.rubberBands):
                punto = puntoR.asGeometry()
                if punto.intersects(geomPunto):
                    indiciUniti.append(ind)
                    geomDaAggiungere = geomDaAggiungere.combine(punto)

            for ind, daRimuovere in enumerate(sorted(indiciUniti)):
                self.rubberBands[daRimuovere-ind].reset(QGis.Polygon)
                self.rubberBandsBorder[daRimuovere-ind].reset(QGis.Line)
                del self.rubberBands[daRimuovere-ind]
                del self.rubberBandsBorder[daRimuovere-ind]

            color = self.getCorrectColor()

            rubberBand = QgsRubberBand(self.canvas, QGis.Polygon)
            rubberBand.setColor(color)
            rubberBand.setWidth(1)

            rubberBandBorder = QgsRubberBand(self.canvas, QGis.Line)
            rubberBandBorder.setColor(QColor(0, 0, 0))
            rubberBandBorder.setWidth(1)

            rubberBand.setToGeometry(geomDaAggiungere, None)
            rubberBandBorder.addGeometry(geomDaAggiungere, None)

            self.rubberBands.append(rubberBand)
            self.rubberBandsBorder.append(rubberBandBorder)



    def chiudiFase(self, button):
        self.rubberBandBorderPointer.reset(QGis.Line)
        self.rubberBandPointer.reset(QGis.Polygon)
        try:
            for ind, geomR in enumerate(self.rubberBands):
                geom = geomR.asGeometry()#.simplify(1)
                if geom:
                    if geom.isGeosValid():
                        res, selectedFeat, lyr = self.getSelectedFeature()
                        if res:
                            oldGeom = selectedFeat.geometry()
                            if geom.intersects(oldGeom):
                                featDaAggiungere = []
                                featDaCancellare = []

                                featDaCancellare.append(selectedFeat.id())
                                feat = QgsFeature()
                                feat.setAttributes(selectedFeat.attributes())
                                #feat.setId(None)
                                if button == Qt.LeftButton:
                                    newGeom = oldGeom.combine(geom)
                                    feat.setGeometry(newGeom)
                                else:
                                    newGeom = oldGeom.difference(geom)
                                    feat.setGeometry(newGeom)

                                if feat.geometry() and feat.geometry().isGeosValid() and feat.geometry().area() > 0.01:
                                    featDaAggiungere.append(feat)

                                lyr.dataProvider().deleteFeatures(featDaCancellare)
                                res, features = lyr.dataProvider().addFeatures(featDaAggiungere)
                                lyr.triggerRepaint()

                                ids = [f.id() for f in features]
                                lyr.setSelectedFeatures(ids)
                            else:
                                QMessageBox.information(None, "", "Your drawing doesn't intersects the selected geometry")

        finally:
            self.reset()

    def getCorrectColor(self):
        if self.leftPressed:
            color = QColor(0, 255, 0, 50) #green

        elif self.rightPressed:
            color = QColor(255, 0, 0, 50) #red
        else:
            color = QColor(255, 255, 255, 50) #white
        return color