"""pinceau utilise pour la selection et la mise a jour des cases du plateau"""
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class Pinceau():
    def __init__(self, plateau):
        self.plateau = plateau

        self._forme = "simple"
        self._epaisseur = 1
        
        self._origine = None
        self._point2 = None
        self._selection = []

        self._objetGraphique = None

        self._actif = False

    def estActif(self):
        return self._actif

    def majForme(self, forme):
        if forme in ["simple", "ligne", "frontiere", "pot", \
                     "rectV", "rectP", "ellipseV", "ellipseP"]:
            self._forme = forme

    def majEpaisseur(self, val):
        if val in range(1, 5):
            self._epaisseur = val

    def defOrigine(self, coord):
        if self.plateau.coordonneesValides(coord):
            self._origine = self.plateau.cases[coord].centreGraphique

    def defPoint2(self, coord):
        if self.plateau.coordonneesValides(coord):
            self._point2 = self.plateau.cases[coord].centreGraphique

    def selection(self):
        return self._selection

    def demarrer(self, coord):
        """commence a peindre a partir de la case choisie comme origine"""
        if self.plateau.coordonneesValides(coord):
            self._origine = self.plateau.cases[coord].centreGraphique
            self._point2 = self.plateau.cases[coord].centreGraphique
            self._actif = True

    def maj(self, coord):
        """on met a jour la selection en fonction de la case qui vient d'etre ajoutee"""
        if self._actif:
            enPlus  = []  #cases a ajouter a la selection
            enMoins = []  #cases a retirer de la selection
            if self._origine == None: self._origine = self.plateau.cases[coord].centreGraphique

            if self._forme == "simple":
                #pas de forme: on ajoute les cases survolees a la liste des cases
                zone = self.plateau.zone(coord, self._epaisseur - 1)
                for coord in zone:
                    if not coord in self._selection:
                        enPlus.append(coord)

            elif self._forme == "frontiere":
                #droite qui selectionne toutes les cases situees au dessus d'elle
                if self._objetGraphique == None:
                    pinceau = QPen()
                    pinceau.setColor(QColor("black"))
                    self._objetGraphique = QGraphicsLineItem()
                    self._objetGraphique.setPen(pinceau)
                    self.plateau.addItem(self._objetGraphique)
                    
                self._point2 = self.plateau.cases[coord].centreGraphique    
                ligne = QLineF(self._origine, self._point2)
                orientation = int((1+int(ligne.angle()/22.5))/2)
                ligne.setAngle(orientation*45)
                self._objetGraphique.setLine(ligne)
                select = self.selectionFrontiere()
                #on met compare avec l'ancienne selection pour minimiser le nombre de cases a maj
                for coord in self._selection:
                    if not coord in select:
                        enMoins.append(coord)
                    else:    
                        select.remove(coord)
                enPlus = select   #toutes les coord qui restent dans select sont a ajouter

            else:    
                if self._forme == "ligne":
                    #segment simple
                    if self._objetGraphique == None:
                        pinceau = QPen()
                        pinceau.setColor(QColor("black"))                    
                        self._objetGraphique = QGraphicsLineItem()
                        self._objetGraphique.setPen(pinceau)
                        self._objetGraphique.prepareGeometryChange()
                        self.plateau.addItem(self._objetGraphique)
                    self._point2 = self.plateau.cases[coord].centreGraphique        
                    ligne = QLineF(self._origine, self._point2)
                    self._objetGraphique.setLine(ligne)                                   
                
                elif self._forme == "rectV" or self._forme == "rectP":
                    #rectangle
                    if self._objetGraphique == None:
                        pinceau = QPen()
                        pinceau.setColor(QColor("black"))
                        self._objetGraphique = QGraphicsRectItem()
                        self._objetGraphique.prepareGeometryChange()
                        self._objetGraphique.setPen(pinceau)
                        self.plateau.addItem(self._objetGraphique)
                    self._point2 = self.plateau.cases[coord].centreGraphique  
                    rect = QRectF(QPointF(min(self._origine.x(), self._point2.x()), min(self._origine.y(), self._point2.y())), \
                                  QPointF(max(self._origine.x(), self._point2.x()), max(self._origine.y(), self._point2.y()))  )
                    self._objetGraphique.setRect(rect)
                
                elif self._forme == "ellipseV" or self._forme == "ellipseP":
                    #ellipse
                    if self._objetGraphique == None:
                        pinceau = QPen()
                        pinceau.setColor(QColor("black"))
                        self._objetGraphique = QGraphicsEllipseItem()
                        self._objetGraphique.prepareGeometryChange()
                        self._objetGraphique.setPen(pinceau)
                        self.plateau.addItem(self._objetGraphique)
                    self._point2 = self.plateau.cases[coord].centreGraphique  
                    rect = QRectF(QPointF(min(self._origine.x(), self._point2.x()), min(self._origine.y(), self._point2.y())), \
                                  QPointF(max(self._origine.x(), self._point2.x()), max(self._origine.y(), self._point2.y()))  )
                    self._objetGraphique.setRect(rect)

                #on liste les cases intersectant la forme
                select = self.casesSousForme(self._objetGraphique, (self._forme[-1:] == "P"))
                
                for coord in self._selection:
                    if not coord in select:
                        enMoins.append(coord)
                    else:    
                        select.remove(coord)
                enPlus = select
                
            for coord in enPlus:
                self.afficherCase(coord, True)
                self._selection.append(coord)
            for coord in enMoins:
                self.afficherCase(coord, False)
                self._selection.remove(coord)
            
    def annuler(self):
        self.reinit()

    def terminer(self):
        return self._selection

    def reinit(self):
        for coord in self._selection:
            self.afficherCase(coord, False)
        if self._objetGraphique:
            self.plateau.removeItem(self._objetGraphique)
            self._objetGraphique = None
        self._origine = None
        self._point2 = None
        self._selection = []
        self._actif = False

    def afficherCase(self, coord, actif):
        self.plateau.cases[coord].majEstCibleCurseur(actif)

    def selectionFrontiere(self):
        """retourne les cases selectionnees lors de l'utilisation de la forme 'frontiere'"""
        listeCases = []
        if self._objetGraphique != None:
            ligne = self._objetGraphique.line()
            normale = ligne.normalVector()
            normale = normale.unitVector()
            coordOrigine = self.plateau.coordonneesAuPoint(self._origine)
            dx = normale.p2().x() - normale.p1().x()
            dy = normale.p2().y() - normale.p1().y()
            for coord in self.plateau.cases:
                if dx < 0 and dy == 0:  #normale pointe vers la gauche
                    if (coord[0] - coordOrigine[0]) <= 0:
                        listeCases.append(coord)
                if dx > 0 and dy == 0:  #normale pointe vers la droite
                    if (coord[0]  - coordOrigine[0]) >= 0:
                        listeCases.append(coord)   
                if dx == 0 and dy < 0:  #pointe vers le haut (rappel: axe y vers le bas)
                    if (coord[1] - coordOrigine[1]) <= 0:
                        listeCases.append(coord)
                elif dx == 0 and dy > 0:  #pointe vers le bas
                    if (coord[1] - coordOrigine[1]) >= 0:
                        listeCases.append(coord)
                if dx > 0 and dy < 0:  #pointe vers le haut droite
                    if (coord[0] - coordOrigine[0]) + -1*(coord[1] - coordOrigine[1]) >= 0:
                        listeCases.append(coord)
                elif dx > 0 and dy > 0:  #pointe vers le bas droite
                    if -1*(coord[0] - coordOrigine[0]) + -1*(coord[1] - coordOrigine[1]) <= 0:
                        listeCases.append(coord)
                if dx < 0 and dy < 0:  #pointe vers le haut gauche
                    if (coord[0] - coordOrigine[0]) + (coord[1] - coordOrigine[1]) <= 0:
                        listeCases.append(coord)
                elif dx < 0 and dy > 0:  #pointe vers le bas gauche
                    if -1*(coord[0] - coordOrigine[0]) + (coord[1] - coordOrigine[1]) >= 0:
                        listeCases.append(coord)
        return listeCases


    def casesSousForme(self, forme, plein = True):
        """renvoie la liste des cases en collision avec un QGraphicsItem en parametre
            plein = False: pas le contenu de la forme
            epaisseur = renvoie aussi les cases voisines jusqu'a la distance demandee"""
        tmp = []
        listeCases = []
        point1 = None
        point2 = None
        #point 1 et 2
        if forme.__class__.__name__ == "QGraphicsLineItem":
            point1 = forme.line().p1()
            point2 = forme.line().p2()
        elif forme.__class__.__name__ == "QGraphicsRectItem" or forme.__class__.__name__ == "QGraphicsEllipseItem":
            point1 = forme.rect().topLeft()
            point2 = forme.rect().bottomRight()
        else:
            point1 = forme.boundingRect().topLeft()
            point2 = forme.boundingRect().bottomRight()            
 
        #preselection des cases (meilleures perf)
        preSelection = []
        if point1 != None and point2 != None and point1 != point2:
            coord1 = self.plateau.coordonneesAuPoint(point1)  
            coord2 = self.plateau.coordonneesAuPoint(point2)
            if coord1 != None and coord2 != None:
                minX = min(coord1[0], coord2[0]) - 1
                maxX = max(coord1[0], coord2[0]) + 1
                minY = min(coord1[1], coord2[1]) - 1
                maxY = max(coord1[1], coord2[1]) + 1
                for coord in self.plateau.cases:
                    if coord[0] >= minX and coord[0] <= maxX and coord[1] >= minY and coord[1] <= maxY :
                        preSelection.append(coord)
            else:
                preSelection = self.cases       
        else:
            for coord in self.plateau.cases:
                preSelection.append(coord)
       
        #on liste les cases en collision avec la forme 
        for coord in preSelection:
            if self.plateau.cases[coord].collidesWithItem(forme, Qt.IntersectsItemShape):
                if plein:
                    tmp.append(coord) 
                else:
                    contenu = True
                    for i in range(0,len(self.plateau.cases[coord].polygon())):
                        if not forme.contains(self.plateau.cases[coord].polygon().at(i)):
                            contenu = False
                            break
                    if contenu == False:
                         tmp.append(coord)    
        #on applique l'epaisseur du pinceau (lignes ou formes vides seulement) si necessaire
        if not plein and self._epaisseur > 0:
            for coord in tmp:
                zone = self.plateau.zone(coord, self._epaisseur - 1)
                for coord2 in zone:
                    if not coord2 in listeCases:
                        listeCases.append(coord2)
        else:
            listeCases = tmp
        #si la liste est vide, on ajoute l'origine de la forme
        if len(listeCases) == 0:
            listeCases = [self.plateau.coordonneesAuPoint(point1)]    
        return listeCases                





    
