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

class Vectorize2Tool(QgsMapToolEmitPoint):
    def __init__(self,
                 canvas,
                 iface,
                ):

        QgsMapToolEmitPoint.__init__(self, canvas)
        self.canvas = canvas
        self.iface = iface
        name = "VectorizeTool"
        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)

    # ========================================= Temp layer ========================================= #

    def createTempLayer(self):
        tempVectorLayer = QgsVectorLayer("Polygon", "temp", "memory")
        stylePath = os.path.dirname(os.path.abspath(__file__))
        stylePath = stylePath[0: stylePath.rfind(os.path.sep)+1]+"styles"+os.path.sep+"vectorStyle.qml"
        tempVectorLayer.loadNamedStyle(stylePath)

        #QMessageBox.information(None, "", str(stylePath))
        results = QgsMapLayerRegistry.instance().addMapLayers([tempVectorLayer])
        cond = tempVectorLayer.isValid() and tempVectorLayer in results
        if cond:
            self.tempVectorLayer = tempVectorLayer
        else:
            QMessageBox.information(None, "", "Vector layer invalid")
        return cond


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

    # ========================================= 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
            N = self.mapGraph.approximation

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

            resultInLAB = True
            rgbColor = self.mapGraph.getRectValue(rect, self.rasterLayer, N, not resultInLAB)
            #QMessageBox.information(None, "", str(rgbColor))

            if rgbColor == (-1,-1,-1): rgbColor = (255,255,255)
            self.pixelOver.emit(rgbColor)

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


    def canvasPointClicked(self, point, button):

        lyr = self.iface.activeLayer()

        if lyr and lyr.type() == QgsMapLayer.RasterLayer:
            self.rasterLayer = lyr
            try:
                if button == Qt.LeftButton:
                    if self.createTempLayer():
                        self.iface.setActiveLayer(self.rasterLayer)

                        featDaAggiungere = []

                        N = self.mapGraph.approximation

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

                        labColorFirst = self.mapGraph.getRectValue(rect, self.rasterLayer, N)
                        geom = QgsGeometry.fromRect(rect)


                        extent = self.canvas.extent()


                        #geom = self.visita(geom, point, rect, self.rasterLayer, labColorFirst, N, extent)
                        geom = self.visitaNotRec(self.rasterLayer, geom, point, labColorFirst, N, extent)
                        if geom == None:
                            QMessageBox.information(
                                None, "Timeout exceeded", ""
                                "<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>"
                            )
                        else:
                            feat = QgsFeature()

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

                            feat.setGeometry(geom)
                            featDaAggiungere.append(feat)

                            """
                            toRemove = []
                            iterF = self.tempVectorLayer.getFeatures()
                            for feat in iterF:
                                toRemove.append(feat.id())
                            iterF.close()
                            self.tempVectorLayer.dataProvider().deleteFeatures(toRemove)
                            """
                            self.rubberBand.reset()

                            self.tempVectorLayer.dataProvider().addFeatures(featDaAggiungere)
                            self.tempVectorLayer.triggerRepaint()


                elif button == Qt.RightButton:
                    pass
            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, N, extent):
        initial_time = time.time()
        visitati = [center]
        daVisitare = self.mapGraph.getAdjacentValidPixels(visitati, center, raster, colorFirst, extent, N)

        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, N)
            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
        return geom

    def visita(self, geom, center, rect, raster, colorFirst,N, extent):
        geomNuova = QgsGeometry.fromRect(rect)
        geom = geom.combine(geomNuova)

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

        adjacentPoints = self.mapGraph.getAllAdjacentPixelPositionsNxN(center, raster, N)

        trovati = []
        directionTrovate = []
        for adjPoint, direction in adjacentPoints:

            if extent.contains(adjPoint):

                adjRect = self.mapGraph.getPixelRectangleNxN(adjPoint, self.rasterLayer, N)
                labColorAdj = self.mapGraph.getRectValue(adjRect, raster, N)

                if self.mapGraph.pixelSimili(colorFirst, labColorAdj):
                    trovati.append((adjPoint,adjRect))
                    directionTrovate.append(direction)

        toIgnore = []
        #for ind, direction in enumerate(directionTrovate):
        #    indVero = self.directions.index(direction)

        #    dirPrecVera = self.directions[(indVero-1)%len(self.directions)]
        #    dirSuccVera = self.directions[(indVero+1)%len(self.directions)]

        #    dirPrecTrovata = directionTrovate[(ind-1)%len(directionTrovate)]
        #    dirSuccTrovata = directionTrovate[(ind+1)%len(directionTrovate)]

        #    if dirPrecVera != dirPrecTrovata and dirSuccVera != dirSuccTrovata:
        #        toIgnore.append(ind)

        for ind,(pointT,rectT) in enumerate(trovati):
            if ind not in toIgnore:
                if not geom.contains(pointT):
                    geom = self.visita(geom, pointT, rectT, raster, colorFirst, N, extent)

        return geom


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