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

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

from Forme import Forme
from outilsSvg import *

class Pion(QGraphicsItem):
    """pion du plateau de combat"""
    def __init__(self, parent=None):
        super(Pion, self).__init__()
        #caracteristiques du pion
        self.numero = 0
        self.nom = ""
        self.couleur = QColor()
        self.logo = ""
        self.img = ImgPion()
        self.etiquette = EtiquettePion()

        #infos liees au plateau (forme et position)
        self.plateau = None
        self.numComplementaire = ""    #numero complementaire si necessaire
                                        #(si plusieurs pions portent le meme nom)
        self.position = (-1, -1)
        self.z = 0
        self.hauteur = 1
        self.forme = None
        self.formeDef = {"H":[], "C":[]}

        #objets et parametres graphiques
        self.pixGraphique = None
        self.etiquetteGraphique = None
        self._l0 = 0
        self._h0 = 0
        self.polygoneGraphique = None
        self.nbRotations = 0

        
    def __getstate__(self):
        nePasSvg = ["plateau", "brillance", "shadow", "creature", "polygonesForme", "pixGraphique", "etiquetteGraphique"]
        state = {key:value for key, value in self.__dict__.items() if not key in nePasSvg}
        return (state)
    
    def __setstate__(self, state):
        self.__dict__ = state
        self.pixGraphique = None
        self.etiquetteGraphique = None
        super(Pion, self).__init__()

    def paint(self, painter, option, widget = None):
        """reimplemente de QGraphicsItem: on ne peint pas cet item, seulement ses items enfants"""
        pass

    def txtId(self):
        """renvoie le nom et le numero complementaire du pion"""
        return "{} {}".format(self.nom, self.numComplementaire)

    def icone(self):
        """renvoie l'image a afficher dans les listes"""
        return self.logo

    def yReel(self):
        """renvoie le y reel (pour les contructions graphiques"""
        if 1 == (self.position[0] % 2):
             y = self.position[1] + 0.5
        else:
             y = self.position[1]
        return y
    
    ###attributs du pion
    def position(self):
        """retourne la position actuelle du pion"""
        return self.position

    def casesOccupees(self):
        """retourne la liste des cases occupees sur le plateau par le pion (x,y,z)"""
        retour = []
        if self.plateau:
            for x, y in self.forme.listeCases(self.position, self.nbRotations):
                for z in range(1, self.hauteur):
                    retour.append((x, y, (self.plateau.cases[(x, y)].altitude + self.z + z)))
        return retour

    def majZ(self, valeur):
        """met a jour l'altitude Z du pion"""
        if valeur != self.z:
            self.z = valeur    

    ########### fonctions graphiques et geometriques   ##############
    def ajouterAuPlateau(self, plateau):
        """cerre l'objet graphique representant le pion et le place sur le plateau"""
        self.plateau = plateau

        #definition de la forme (interpretation de formeDef)
        self.forme = Forme(self.plateau.formeCases)
        if len(self.formeDef[self.plateau.formeCases]) > 0:
            self.forme.definirForme(self.formeDef[self.plateau.formeCases])        

        #creation du polygone
        polygone = self.plateau.polygoneAgglo(self.forme.listeCases((0,0)))
        self.polygoneGraphique = QGraphicsPolygonItem()
        self.polygoneGraphique.setPolygon(polygone)
        self.polygoneGraphique.setAcceptHoverEvents(True)
        self.polygoneGraphique.setFlag(QGraphicsItem.ItemIsFocusable)   #l'item peut recevoir des commandes souris/clavier
        self.polygoneGraphique.setParentItem(self)
        self.polygoneGraphique.setPos(QPointF(0,0))
        if self.plateau.formeCases == "H":
            self.polygoneGraphique.setTransformOriginPoint(QPointF(2*0.2886*self.plateau.hCase, 0.5*self.plateau.hCase))
        else:
            self.polygoneGraphique.setTransformOriginPoint(QPointF(0.5*self.plateau.hCase,0.5*self.plateau.hCase))

        #parametres de l'objet graphique
        self.setZValue(10)
        self.setFlag(QGraphicsItem.ItemHasNoContents)
        self.setHandlesChildEvents(True)
         
        pinceau = QPen()
        pinceau.setColor(self.couleur.darker(130))
        pinceau.setWidth(10)
        self.polygoneGraphique.setPen(pinceau)

        if self.couleur.isValid():
             self.polygoneGraphique.setBrush(self.couleur)
        else:
             self.polygoneGraphique.setBrush(QColor(255, 0, 0, 150))

        self.shadow = QGraphicsDropShadowEffect()
        self.shadow.setColor(QColor(50, 50, 50)) 
        self.shadow.setXOffset(1) 
        self.shadow.setYOffset(2) 
        self.shadow.setBlurRadius(3)  
        self.shadow.setEnabled(True)
        self.polygoneGraphique.setGraphicsEffect(self.shadow)
        
        self.polygoneBrillance = QGraphicsPolygonItem()
        self.polygoneBrillance.setPolygon(self.polygoneGraphique.polygon())
        self.polygoneBrillance.setVisible(False)
        self.polygoneGraphique.setFlag(QGraphicsItem.ItemIsFocusable)
        self.setAcceptHoverEvents(True)   #accepte les evenements survol souris
        self.polygoneBrillance.setParentItem(self.polygoneGraphique)

        #on ajoute l'objet au plateau
        self.plateau.addItem(self)
        self.majPosition(self.position, self.nbRotations)

    def majPosition(self, nouvellePosition, nbRotations = 0):
        """met a jour la position de l'objet graphique et de sa forme en fonction de sa position enregistree"""
        if self.plateau:
            #on met a jour l'occupation des cases
            if self.position != (-1,-1):
                for coord in self.forme.listeCases((self.position[0],self.position[1]), self.nbRotations):
                    self.plateau.cases[coord].majOccupation(self)

            #on met a jour la position du pion        
            self.position = nouvellePosition
            self.majNbRotation(nbRotations)

            #on replace
            if self.plateau.formeCases == "H":
                angleRotation = 60
                positionGraphique = QPointF(self.position[0] * 0.866 * self.plateau.hCase, self.yReel() * self.plateau.hCase)
            else:
                angleRotation = 90
                positionGraphique = QPointF(self.position[0] * self.plateau.hCase, self.position[1] * self.plateau.hCase)
            self.prepareGeometryChange()
            self.setPos(positionGraphique)
            self.polygoneGraphique.setRotation(self.nbRotations*angleRotation)
            
            #maj de l'image
            self.majImage()
            
            #on met a jour l'occupation des cases
            for coord in self.forme.listeCases((self.position[0],self.position[1]), self.nbRotations):
                 self.plateau.cases[coord].majOccupation(self, self.z)
                 
    def majImage(self):
        """met a jour la taille, la position et l'orientation de l'image"""
        if len(self.img.nomFichier) > 0:
            pix = QPixmap(QString.fromUtf8(self.img.nomFichier))
            if not pix.isNull():
                if not self.pixGraphique:
                    self.pixGraphique = QGraphicsPixmapItem()
                    self.pixGraphique.setZValue(10) 
                    if pix.height() >= pix.width():
                        pix = pix.scaledToHeight(self.plateau.hCase*0.9, Qt.SmoothTransformation)
                    else:
                        pix = pix.scaledToWidth(self.plateau.hCase*0.9, Qt.SmoothTransformation)
                    self._l0 = pix.width()
                    self._h0 = pix.height()
                    pix = pix.scaled((self.img.kx/10)*pix.width(), \
                                     (self.img.ky/10)*pix.height(), \
                                      Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
                    self.pixGraphique.setPixmap(pix)

##                deltaX = self.img.dx + 0.5*(self.plateau.hCase*1.1544 - self._l0)
##                deltaY = self.img.dy + 0.5*(self.plateau.hCase - self._h0)
                deltaX = self.img.dx + 0.5*(self.plateau.hCase*1.1544 - self.pixGraphique.pixmap().width())
                deltaY = self.img.dy + 0.5*(self.plateau.hCase - self.pixGraphique.pixmap().height())
                    
                if self.img.nomFichier == self.logo:
                    #si l'image est le logo, elle ne doit pas pivoter
                    self.pixGraphique.setParentItem(self)
                else:
                    self.pixGraphique.setParentItem(self.polygoneGraphique)
                self.pixGraphique.setRotation(self.img.rotation)
                self.pixGraphique.setPos(QPointF(deltaX, deltaY))

    def majEtiquette(self):
        """met a jour la taille, le format et l'orientation de l'etiquette"""
        self.etiquetteGraphique = QGraphicsSimpleTextItem("{}".format(self.txtId()))
        self.etiquetteGraphique.setPos(QPointF(self.etiquette.dx - 0.112*self.plateau.hCase, \
                                                self.etiquette.dy - 0.5*self.plateau.hCase))
        police = QFont("Verdana", self.etiquette.taille_police)
        police.setBold(self.etiquette.gras)
        self.etiquetteGraphique.setFont(police)
        self.etiquetteGraphique.setParentItem(self)        
                
    def majNbRotation(self, nbRotations):
        """ajoute/retranche le nombre au nombre total de rotations du pion"""
        self.nbRotations = nbRotations
        if self.plateau.formeCases == "H":
            rotationsTour = 6
        else:
            rotationsTour = 4
            
        if self.nbRotations >= 0:
            self.nbRotations = self.nbRotations % rotationsTour
        else:
            self.nbRotations = self.nbRotations % (-rotationsTour)

    def retirerDuPlateau(self):
        """'deconnecte' les items enfants avant de supprimer du pion du plateau"""
        self.polygoneBrillance.prepareGeometryChange()
        self.polygoneBrillance.setParentItem(None)
        if self.pixGraphique != None:
            self.pixGraphique.prepareGeometryChange()
            self.pixGraphique.setParentItem(None)
        self.polygoneGraphique.prepareGeometryChange()
        self.polygoneGraphique.setParentItem(None)
        if self.etiquetteGraphique:
            self.etiquetteGraphique.prepareGeometryChange()
            self.etiquetteGraphique.setParentItem(None)
        self.plateau.removeItem(self)
        self.plateau = None

    ###effets graphiques 
    def afficheOmbreSelection(self, actif = False):
        """modifie l'ombre du pion en fonction de si celui-ci est selectionne ou non"""
        if actif:
            self.shadow.setXOffset(3) 
            self.shadow.setYOffset(3)
        else:
            self.shadow.setXOffset(1) 
            self.shadow.setYOffset(2)
            
    def surbrillance(self, active, opacite = 0.7, couleur = "white"):
        """active/desactive la surbrillance"""
        if active:
            self.polygoneBrillance.setOpacity(opacite)
            couleur = self.couleurSurbrillance(couleur)
            pinceau = self.polygoneGraphique.pen()
            self.polygoneBrillance.setBrush(couleur)
            self.polygoneBrillance.setPen(pinceau)
        self.polygoneBrillance.setVisible(active)
        
    def estCibleAttaque(self, estCible, possible = True):
        """le pion s'affiche comme etant cible d'une attaque"""
        if not possible:
            couleur = "red"
        else:
            couleur = "white"
        self.surbrillance(estCible, 0.8, couleur)
        
    def couleurSurbrillance(self, couleur = "white"):
        """renvoie une QColor visible pour la surbrillance, selon la couleur du pion"""
        retour = QColor(couleur)
        if self.polygoneGraphique.brush().color().lightness() > 220:
            retour = retour.darker(140)
        elif self.polygoneGraphique.brush().color().lightness() < 80:
            retour = retour.lighter(140)
        return retour

    ##################

    ###############   evenements clavier et souris    ##############
    def boundingRect(self):
        return QRectF()

        
     #######################

class ImgPion():
    def __init__(self):
        self.nomFichier = ""        #nom du fichier image source
        self.kx = 10                 #coeff d'agrandissement horizontal
        self.ky = 10                 #coeff d'agrandissement vertical
        self.dx = 0                 #decalage horizontal
        self.dy = 0                 #decalage vertical
        self.rotation = 0           #rotation(en degres)
        self.pivote = False         #l'image pivote avec le pion?
        self.masqueAuto = False     #creer un masque automatiquement
        
class EtiquettePion():
    def __init__(self):
        self.txt = ""
        self.taille_police = 28     #taille de la police
        self.gras = False           #en gras
        self.dx = 0                 #decalage horizontal
        self.dy = 0                 #decalage vertical

