#from __future__ import unicode_literals
# -*- coding: utf-8 -*-
from __future__ import division
import os

from PyQt4.QtCore import *
from PyQt4.QtGui import *

from Pion import ImgPion, EtiquettePion

class VueEditionForme(QGraphicsScene):
    """vue graphique permettant d'afficher et de modifier la forme des creatures/decors"""
    def __init__(self, fenetre, parent=None):   
        super(VueEditionForme, self).__init__()
        self.fenetre = fenetre
        
        self._vefImage = VefImage(self)
        self._vefEtiquette = VefEtiquette(self)
        self._couleur = QColor(190,190,190,255)

        self._cases = {}
        self._formeCases = "H"
       
        self._l0 = 0
        self._h0 = 0
        self._rotation = 0
        self.selection = None

        self.fenetre.ui.edc_vueForme.setScene(self)    
        self.fenetre.ui.edc_vueForme.centerOn(self.fenetre.ui.edc_vueForme.mapFromScene(QPointF(60,60)))   #centre la vue sur la case 0,0
        self.fenetre.ui.edc_vueForme.scale(0.22, 0.22)

    def setCursor(self, curseur):
        self.fenetre.ui.edc_vueForme.setCursor(curseur)

    #acces aux donnees
    def chargerFormeDef(self, formeDef):
        self._formeDef = formeDef
        self._majFormeGraphique()

    def formeDef(self):
        """renvoie la definition de forme (selon la forme des cases actuelle)"""
        retour = []
        for coord in self._cases:
            if self._cases[coord].estSelectionnee() and coord != (0,0):
                retour.append(coord)
        return retour      

    def chargerEtiquetteDef(self, etiquetteDef):
        self._vefEtiquette.charger(etiquetteDef)

    def etiquetteDef(self):
        return self._vefEtiquette.definition()

    def chargerImageDef(self, imgDef):
        self._vefImage.charger(imgDef)

    def nouvelleImageDef(self, cheminFichier):
        imgDef = ImgPion()
        imgDef.nomFichier = cheminFichier
        self._vefImage.charger(imgDef)

    def imageDef(self):
        return self._vefImage.definition()
    
    def majCouleur(self, couleur):
        """met a jour la couleur du pion"""
        self._couleur = couleur
        self._majCouleurGraphique()

    def couleur(self):
        return self._couleur

    def formeCases(self):
        return self._formeCases

    #creation, suppression, mises a jour...
    def creer(self, formeCases = "H"):
        self._formeCases = formeCases
        
        for x in range(-5,6):
            for y in range(-5,6):
                if not ((x%2)==1 and y == -5):
                    c = VefCase(self)
                    c.creer(x, y, self._couleur, self._formeCases)
                    self._cases[(x,y)] = c

    def vider(self):
        for coord in self._cases:
            self.removeItem(self._cases[coord])
        self._cases = {}

    def _majFormeGraphique(self):
        """met a jour la forme affichee sur le graphique"""
        if self._formeDef:
            for coord in self._formeDef:
                if coord in self._cases:
                    self._cases[coord].selectionner(True)
                    self._cases[coord].setBrush(self._couleur)

    def _majCouleurGraphique(self):
        for coord in self._cases:
            if self._cases[coord].estSelectionnee():
                if coord == (0,0):
                    c = self._couleur.darker(150)
                    self._cases[coord].setBrush(c)
                else:
                    self._cases[coord].setBrush(self._couleur)

    def majSelection(self, coord):
         """met a jour l'affichage des cases selectionnees pour l'affichage de la forme"""
         if self._cases[coord].estSelectionnee():
             valide = True
             for coordVerif in self._cases:
                 #on parcourt les autres cases selectionnees
                 if coordVerif != (0,0) and coordVerif != coord and self._cases[coordVerif].estSelectionnee():
                     #on liste les cases connectees a cette case, de proche en proche
                     connectees = [coordVerif]
                     for coordVerif2 in connectees:
                         for coordVoisin in self._cases[coordVerif2].voisins():
                             if coordVoisin in self._cases and not coordVoisin in connectees:
                                 if self._cases[coordVoisin].estSelectionnee():
                                     connectees.append(coordVoisin)
                     if not (0,0) in connectees:
                         valide = False
                         break
             if valide:
                 self._cases[coord].selectionner(False)
         else:
             #on s'assure que la case est bien adjacente a une case selectionnee
             valide = False
             for coordVerif in self._cases[coord].voisins():
                if coordVerif in self._cases:
                    if self._cases[coordVerif].estSelectionnee():
                        valide = True
                        break
             if valide:
                 self._cases[coord].selectionner(True)
                 
         self._majCouleurGraphique()


    def afficherMsg(self, msg):
        print msg
  


class VefCase(QGraphicsPolygonItem):
    """case utilisee dans une VueEditionForme()"""
    def __init__(self, scene, parent=None):
        super(VefCase, self).__init__()
        self.scene = scene
        self._position = (0,0)
        self._estSelectionnee = False
        self._voisins = []
        self._couleur = None
        
        #interactions graphiques
        self.setFlag(QGraphicsItem.ItemIsFocusable)
        self.setAcceptHoverEvents(True)

    def estSelectionnee(self):
        return self._estSelectionnee

    def selectionner(self, actif):
        if actif:
            self.setBrush(self._couleur)
        else:
            self.setBrush(QColor(255,255,255,50))
        self._estSelectionnee = actif

    def voisins(self):
        return self._voisins

    def creer(self, x, y, couleur, formeCases="H"):
        """creation du polygone et enregistrement des donnees geometriques"""
        self._position = (x, y)
        
        polygone = QPolygonF()
        
        if formeCases == "H":
            my = 0
            if (x % 2) == 1: my = -0.5
            polygone  << QPointF(((x*0.866)+0.2886)*120, (y+my)*120) \
                      << QPointF(((x*0.866)+0.866)*120,  (y+my)*120) \
                      << QPointF(((x*0.866)+1.1547)*120, (y+my+0.5)*120) \
                      << QPointF(((x*0.866)+0.866)*120,  (y+my+1)*120) \
                      << QPointF(((x*0.866)+0.2886)*120, (y+my+1)*120)  \
                      << QPointF( (x*0.866)*120,         (y+my+0.5)*120)
        else:
            polygone  << QPointF(x*120,      y*120) \
                      << QPointF((x+1)*120,  y*120) \
                      << QPointF((x+1)*120,  (y+1)*120) \
                      << QPointF(x*120,      (y+1)*120)          
        self.setPolygon(polygone)

        #enregistrement des cases voisines:       
        if formeCases == "H":
            self._voisins = [(x, y-1), (x+1, y-1), (x+1, y), (x,  y+1), (x-1, y), (x-1, y-1)]
        else:
            self._voisins.append((x,   y-1))
            self._voisins.append((x,   y+1))
            self._voisins.append((x-1, y))
            self._voisins.append((x+1, y))

        #pour afficher les coordonnees des cases:        
##        text = QGraphicsSimpleTextItem("{} {}".format(x, y), parent=self)
##        police = QFont()
##        police.setPointSize(20)
##        text.setFont(police)
##        k = 0
##        if (x % 2) == 1: k = - 0.5
##        text.setPos(QPointF(((x*0.866)+0.5773)*120, (y+0.5+k)*120))

        #couleur de fond par defaut
        if couleur.__class__.__name__ == "QColor":
            if couleur.isValid():
                self._couleur = couleur
            else:
                self._couleur = QColor("grey")
        else:
            self._couleur = QColor("grey")
        
        if self._position == (0, 0):
            couleur = self._couleur.darker(150)
            self.setBrush(couleur)
            self._estSelectionnee = True
        else:    
            self.selectionner(False)
            
        #creation de l'objet graphique sur le plateau
        pinceau = QPen()
        pinceau.setWidth(2)
        pinceau.setColor(QColor(150,150,150,150))
        self.setPen(pinceau)
        self.scene.addItem(self)

    def mousePressEvent(self, event):
        """evenement lors du clic souris"""
        super(VefCase, self).mousePressEvent(event)
        if event.button() == 1: #sur clic gauche
            if self._position != (0, 0):
                self.scene.majSelection(self._position)



class VefImage(QGraphicsPixmapItem):
    """etiquette utilisee dans une VueEditionForme()"""
    def __init__(self, scene, parent=None):
        super(VefImage, self).__init__()
        self.scene = scene
        self._def = ImgPion()
        self._pix = None
        self._l0 = 0
        self._h0 = 0
        self.setAcceptDrops(True)
        self.setAcceptHoverEvents(True)
        self.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable)
        self.scene.addItem(self)
        self.setZValue(10)
        
    def charger(self, definition):
        self._pix = None
        self._l0 = 0
        self._h0 = 0
        self._def = definition
        self._maj()

    def definition(self):
        return self._def

    def _maj(self):
        if len(self._def.nomFichier) > 0:
            if self._pix == None:
                self._pix = QPixmap(QString.fromUtf8(self._def.nomFichier))
                if not self._pix.isNull():
                    if self._pix.height() >= self._pix.width():
                        self._pix = self._pix.scaledToHeight(120*0.9, Qt.SmoothTransformation)
                    else:
                        self._pix = self._pix.scaledToWidth(120*0.9, Qt.SmoothTransformation)
                    self._l0 = self._pix.width()
                    self._h0 = self._pix.height()
                else:
                    self._pix = None
        else:
            self_pix = None
            
        if self._pix:
            taille = QSize((self._def.kx/10)*self._l0, (self._def.ky/10)*self._h0)
            self._pix = self._pix.scaled(taille, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
            k = 1
            if self.scene.formeCases() == "H": k = 1.1544
            deltaX = self._def.dx + 0.5*(120*k - self._pix.width())
            deltaY = self._def.dy + 0.5*(120 - self._pix.height())        
            
            self.setPixmap(self._pix)
            self.setPos(QPointF(deltaX, deltaY))
            self.setRotation(self._def.rotation)


    def width(self):
        return self.boundingRect().width()

    def height(self):
        return self.boundingRect().height()

    def majPos(self, pos):
        k = 1
        if self.scene.formeCases() == "H": k = 1.1544
        self._def.dx = pos.x() - 0.5*(120*k - self._pix.width())
        self._def.dy = pos.y() - 0.5*(120 - self._pix.height())

    def mousePressEvent(self, event):
        self.prepareGeometryChange()
        self.scene.afficherMsg("Utilisez les touches Z, Q, S, D pour modifier la taille de l'image\n" \
                               "Utilisez les touches W et X pour faire pivoter l'image")

    def mouseReleaseEvent(self, event):
        self.scene.afficherMsg("")
        super(VefImage, self).mouseReleaseEvent(event)
        QApplication.processEvents()
        self.majPos(self.scenePos())

    def keyPressEvent(self, event):
        if event.key() in [Qt.Key_Z, Qt.Key_Q, Qt.Key_S, Qt.Key_D, Qt.Key_W, Qt.Key_X]:
            if event.key() == Qt.Key_Z:
                self._def.ky += 2
            elif event.key() == Qt.Key_Q:
                self._def.kx -= 2
            elif event.key() == Qt.Key_S:
                self._def.ky -= 2
            elif event.key() == Qt.Key_D:
                self._def.kx += 2
            elif event.key() == Qt.Key_W:
                self._def.rotation -= 5
            elif event.key() == Qt.Key_X:
                self._def.rotation += 5

            self.majPos(self.scenePos())
            self._maj()


class VefEtiquette(QGraphicsSimpleTextItem):
    """etiquette utilisee dans une VueEditionForme()"""
    def __init__(self, scene, parent=None):
        super(VefEtiquette, self).__init__()
        self.scene = scene
        self._def = EtiquettePion()
        self.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable)
        self.setAcceptDrops(True)
        self.setAcceptHoverEvents(True)
        
        self.scene.addItem(self)
        self.setZValue(10)
        
        
    def charger(self, definition):
        self._def = definition
        self._maj()

    def definition(self):
        return self._def

    def _maj(self):
        if len(self._def.txt) > 0:
            self.setText(QString.fromUtf8(self._def.txt))
            self.setPos(QPointF(self._def.dx - 0.112*120, self._def.dy - 0.5*120))

            police = QFont("Verdana", self._def.taille_police)
            police.setBold(self._def.gras)
            self.setFont(police)

    def majPos(self, pos):
        self._def.dx = pos.x() - 0.112*120
        self._def.dy = pos.y() - 0.5*120        

    def mousePressEvent(self, event):
        self.prepareGeometryChange()
        self.scene.afficherMsg("Utilisez les touches HAUT et BAS pour modifier la taille de la police\n" \
                               "Utilisez la touche G pour activer/desactiver l'écriture en gras")

    def mouseReleaseEvent(self, event):
        self.scene.afficherMsg("")
        super(VefEtiquette, self).mouseReleaseEvent(event)
        QApplication.processEvents()
        self.majPos(self.scenePos())

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Up:
            self._def.taille_police += 4
            self.majPos(self.scenePos())
            self._maj()
        elif event.key() == Qt.Key_Down:
            self._def.taille_police -= 4
            self.majPos(self.scenePos())
            self._maj()
        elif event.key() == Qt.Key_G:
            if not self._def.gras:
                self._def.gras = True
            else:
                self._def.gras = False
            self.majPos(self.scenePos())
            self._maj()
        
             
                










                
