# -*- coding: utf-8 -*-
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from qgis.core import *
from qgis.gui import *
import traceback, os, signal
import time

class VectorizeTool(QgsMapToolEmitPoint):
    def __init__(self,
                 canvas,
                 iface,
                 mapGraph
                ):

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

        self.setObjectName(name)

        self.mapGraph = mapGraph

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

        self.rubberBand = QgsRubberBand(self.canvas, QGis.Polygon)
        self.rubberBand.setColor(Qt.blue)
        self.rubberBand.setWidth(5)


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

        self.canvasClicked.connect(self.canvasPointClicked)




    # ========================================= Setters ============================================ #

    def setTolerance(self, v):
        self.mapGraph.tolerance = v

    def setApproximation(self, a):
        self.mapGraph.approximation = a

    def setViewSteps(self, a):
        self.mapGraph.viewSteps = a

    def setTimeout(self, a):
        self.mapGraph.timeout = a

    # ========================================= 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.rubberBand.reset(QGis.Polygon)
        self.rubberBandPointer.reset(QGis.Polygon)
        self.rubberBandBorderPointer.reset(QGis.Line)
        rgbColor = (255, 255, 255)
        self.pixelOver.emit(rgbColor)

    # ========================================= OnClick ============================================= #


    def canvasMoveEvent(self, event):

        lyr = self.iface.activeLayer()
        if lyr and lyr.type() == QgsMapLayer.RasterLayer:
            point = self.canvas.getCoordinateTransform().toMapPoint(event.x(), event.y())
            self.rasterLayer = lyr

            rect = self.mapGraph.getPixelRectangleNxN(point, self.rasterLayer)
            geom_rect = QgsGeometry.fromRect(rect)
            self.rubberBandPointer.setToGeometry(geom_rect, None)
            self.rubberBandBorderPointer.reset(QGis.Line)
            self.rubberBandBorderPointer.addGeometry(geom_rect, None)

            #rgbColor = self.mapGraph.getRectValue(rect, self.rasterLayer)[1]
            #QMessageBox.information(None, "", str(rgbColor))
            r, g, b = self.rasterLayer.dataProvider().identify(point, QgsRaster.IdentifyFormatValue).results().values()
            if r != None and g != None and b != None:
                rgbColor = (r,g,b)
            else:
                rgbColor = (255,255,255)
            self.pixelOver.emit(rgbColor)

    # ========================================= OnClick ============================================= #

    def keyPressEvent(self, e):
        #16777220 16777221
        #QMessageBox.information(None, "", str(Qt.Key_Enter))
        if e.key() == Qt.Key_Return:
            #QMessageBox.information(None, "", "de")
            self.vectorLayerRequired.emit()
            if self.tempVectorLayer and self.tempVectorLayer.isValid():
                self.tempVectorLayer.setSelectedFeatures([])

    def canvasPointClicked(self, point, button):


        self.vectorLayerRequired.emit()
        if self.tempVectorLayer and self.tempVectorLayer.isValid():
            self.iface.setActiveLayer(self.rasterLayer)

            selected = self.tempVectorLayer.selectedFeatures()
            if len(selected) > 1:
                QMessageBox.information(None, "Warning", "Too many selected features, try again")
                self.tempVectorLayer.setSelectedFeatures([])
            else:
                lyr = self.iface.activeLayer()

                if lyr and lyr.type() == QgsMapLayer.RasterLayer:
                    self.rasterLayer = lyr
                    try:
                        if button == Qt.LeftButton or button == Qt.RightButton:



                            rect = self.mapGraph.getPixelRectangleNxN(point, self.rasterLayer)

                            colorFirst = self.mapGraph.getRectValue(rect, self.rasterLayer)
                            labColorFirst = colorFirst[0]
                            rgbColorFirst = colorFirst[1]
                            if rgbColorFirst != (-1,-1,-1):
                                geom = QgsGeometry.fromRect(rect)


                                extent = self.canvas.extent()

                                geom = self.visitaNotRec(self.rasterLayer, geom, point, labColorFirst, extent)
                                if geom == None:
                                    QMessageBox.information(None, "Timeout exceeded", self.getErrorMessage())
                                else:

                                    geom = geom.simplify(1)
                                    geom = geom.smooth(1, 0.25)

                                    featDaAggiungere = []
                                    featDaCancellare = []

                                    feat = QgsFeature()

                                    if len(selected) == 1:
                                        selectedFeat = selected[0]
                                        selectedGeom = selectedFeat.geometry()
                                        if geom.intersects(selectedGeom):
                                            if button == Qt.LeftButton:
                                                newGeom = selectedGeom.combine(geom)
                                            else:
                                                newGeom = selectedGeom.difference(geom)
                                            feat.setGeometry(newGeom)
                                            featDaCancellare.append(selectedFeat.id())
                                        else:
                                            feat.setGeometry(geom)
                                    else:
                                        feat.setGeometry(geom)

                                    featDaAggiungere.append(feat)
                                    res, features = self.tempVectorLayer.dataProvider().addFeatures(featDaAggiungere)
                                    self.tempVectorLayer.dataProvider().deleteFeatures(featDaCancellare)
                                    self.tempVectorLayer.triggerRepaint()

                                    ids = [f.id() for f in features]
                                    self.tempVectorLayer.setSelectedFeatures(ids)
                            else:
                                QMessageBox.information(None, "Error", "Please select a point within the active raster layer.")

                    except:
                        tb = traceback.format_exc()
                        QMessageBox.information(None, "Attenzione", "Error in canvasPointClicked:\n"+str(tb))
                else:
                    QMessageBox.information(None, "Attenzione", "The active layer must be raster")

    def visitaNotRec(self, raster, geom, center, colorFirst, extent):
        initial_time = time.time()
        visitati = [center]
        daVisitare = self.mapGraph.getAdjacentValidPixels(visitati, center, raster, colorFirst, extent)

        while daVisitare != []:
            curr_point, curr_rect, direction = daVisitare.pop(0)

            visitati.append(curr_point)

            nuovi_daVisitare = self.mapGraph.getAdjacentValidPixels(visitati,curr_point, raster, colorFirst, extent)
            daVisitare = nuovi_daVisitare + daVisitare
            curr_geom = QgsGeometry.fromRect(curr_rect).buffer(0.001, 1)
            geom = geom.combine(curr_geom)

            if self.mapGraph.viewSteps:
                self.rubberBand.setToGeometry(geom, None)
                QMessageBox.information(None, "", "")

            if time.time() - initial_time > self.mapGraph.timeout:
                daVisitare = []
                geom = None
        self.rubberBand.reset()
        return geom

    def getErrorMessage(self):
        return """
                    <p>The process is taking more than <b>"""+str(self.mapGraph.timeout)+""" seconds</b>.</p>

                    <p>If the clicked contiguous area is large in relation
                    with the pixels size is suggested to
                    <b>increase approximation</b> from settings.</p>

                    <p>If the border of the clicked area is not well defined,
                    is suggested to <b>decrise tollerance</b> from settings.</p>

                    <p>It is also possible to change the  <b>timeout</b> from the settings.<p>

               """
    # ========================================= Signals ============================================= #
    pixelOver = pyqtSignal(object)
    vectorLayerRequired = pyqtSignal()
