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

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

from Creature import Creature
from Forme import Forme
from outilsSvg import *

class Pion(QGraphicsItem):
    """pion du plateau de combat"""
    def __init__(self, plateau, numero, parent=None):
        super(Pion, self).__init__()
        #plateau
        self.plateau = plateau

        #attributs
        self.numero = numero
        self.creature = Creature()
        self.nom = "pion"
        self.numTxt = ""
        self.lstCarac = self.creature.listeCarac()   #caracteristiques par defaut issues des regles utilisees
        self.position = (-1, -1)
        self.forme = Forme(self.plateau.formeCases)
        self.champDeplacement = {}   #dictionnaire des cases jusqu'auquelles le pion peut se deplacer (coordonnees : distance)
        self.deplacementRestant = 0
        self.z = 0         #hauteur z par rapport a l'altitude de la case occupee
        self.hauteur = 1   #nombre de cases occupees en hauteur
        self.pixGraphique = None
        self.largeurOriginale = 0
        self.hauteurOriginale = 0
        self.polygoneGraphique = None
        self.nbRotations = 0
        self.etat = ""
        self.attaques = []   #liste des attaques pre-parametrees du pion
        self.notes = ""


    def __getstate__(self):
        self.idCreature = self.creature.id
        state = {key:value for key, value in self.__dict__.items() if not key in ["plateau", "brillance", "shadow", "creature", \
                                                                                  "polygonesForme", "pixGraphique"]}
        return (state)

    def __setstate__(self, state):
        self.__dict__ = state
        self.creature = charger("lib\\biblio\\creature", self.idCreature)
        if self.creature == None:
            self.creature = Creature()


    def paint(self, painter, option, widget = None):
        """reimplemente de QGraphicsItem"""
        pass

    def txtId(self):
        """renvoie le nom et le numero complementaire du pion"""
        return "{} {}".format(self.nom, self.numTxt)
    
    ########### fonctions graphiques et geometriques   ##############
    def creer(self, posX, posY, nom, numTxt = "", creature = None, couleur = None, nbRotations = 0):
        """place le pion sur le plateau"""        
        #definition de la forme  
        if creature != None:
            self.creature = creature  
            if len(self.creature.formeDef[self.plateau.formeCases]) > 0:
                self.forme.definirForme(self.creature.formeDef[self.plateau.formeCases])
            self.attaques = creature.listeAttaques()
            self.lstCarac = self.creature.listeCarac()
        else:
            if couleur != None:
                if couleur.isValid():
                    self.creature.couleur = couleur
                    
        self.creerPolygone()
        self.deplacementRestant = self.creature.deplacement
        
        self.nom = nom
        self.numTxt = numTxt
        
        #aspect graphique
        self.majAspectGraphique()

        #ajout de l'objet graphique
        self.plateau.addItem(self)

        #enregistrement et maj de la position
        self.majPosition((posX, posY), nbRotations)

    def recreer(self, plateau):
        """recree le pion (apres un chargement du plateau par ex)"""
        self.plateau = plateau  
        super(Pion, self).__init__()
        self.pixGraphique = None
        self.polygoneGraphique = None
        self.creerPolygone()
        self.majAspectGraphique()
        self.plateau.addItem(self)
        self.majPosition(self.position, self.nbRotations)

    def creerPolygone(self):
        """cree le polygone representant le pion (doit etre cree avant toute rotation)"""
        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))

    def majAspectGraphique(self):
        """met a jour l'aspect graphique du pion
          (seulement les parametres independants de la position et de la forme de l'objet)"""
        self.setZValue(10)
           
        #interactions graphiques
##        self.setFlag(QGraphicsItem.ItemIsFocusable)   #l'item peut recevoir des commandes souris/clavier
        self.setFlag(QGraphicsItem.ItemHasNoContents) #inutile de peindre l'item
##        self.setAcceptHoverEvents(True)   #accepte les evenements survol souris
        self.setHandlesChildEvents(True)

        #classes graphiques
        self.brillance = QGraphicsColorizeEffect()
        self.shadow = QGraphicsDropShadowEffect()
         
        #etiquette         
        self.text = QGraphicsSimpleTextItem("{}. {}".format(self.numero, self.txtId()))
        self.text.setPos(QPointF(self.creature.txt["dx"]-0.112*self.plateau.hCase, self.creature.txt["dy"]-0.275*self.plateau.hCase))
        police = QFont("Georgia", self.creature.txt["taille_police"])
        police.setBold(self.creature.txt["gras"])
        self.text.setFont(police)
        self.text.setRotation(self.creature.txt["rotation"])
        self.text.setParentItem(self)

        #bordure
        pinceau = QPen()
        pinceau.setColor(self.creature.couleur.darker(130))
        pinceau.setWidth(10)
        self.polygoneGraphique.setPen(pinceau)
            
        #couleur de fond 
        if self.creature.couleur.isValid():
             self.polygoneGraphique.setBrush(self.creature.couleur)
        else:
             self.polygoneGraphique.setBrush(QColor(255, 0, 0, 150))
        
        #ombre
        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)

        #brillance (invisible par defaut, est un polygone semi transparent superpose au pion)
        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)

    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"""
        valide = True  
        if nouvellePosition in self.champDeplacement and self.plateau.modePrincipal == "combat":
            distanceParcourue = self.champDeplacement[nouvellePosition]
            if distanceParcourue <= self.deplacementRestant:
                self.deplacementRestant -= distanceParcourue
            else:
                print ("pas assez de points de deplacement")
                valide = False

        if valide:
            #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.position[1] * 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.creature.img["nom"]) > 0:
            pix = QPixmap(QString.fromUtf8("img\\"+self.creature.img["nom"]))
            if self.creature.img["masqueAuto"]:
                pix.setMask(pix.createHeuristicMask())
            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.largeurOriginale = pix.width()
                    self.hauteurOriginale = pix.height()
                    pix = pix.scaled((self.creature.img["kx"]/10)*pix.width(), \
                                     (self.creature.img["ky"]/10)*pix.height(), \
                                      Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
                    self.pixGraphique.setPixmap(pix)

                deltaX = self.creature.img["dx"] + 0.5*(self.plateau.hCase*1.1544 - self.largeurOriginale)
                deltaY = self.creature.img["dy"] + 0.5*(self.plateau.hCase - self.hauteurOriginale)
                if self.creature.img["nom"] != self.creature.logo and self.creature.img["pivote"] == True:
                    self.pixGraphique.setParentItem(self.polygoneGraphique)
                else:
                    self.pixGraphique.setParentItem(self)
                self.pixGraphique.setRotation(self.creature.img["rotation"])
                self.pixGraphique.setPos(QPointF(deltaX, deltaY))

    def majNbRotation(self, nbRotations):
        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 afficheOmbreSelection(self, actif = False):
        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 majZ(self, valeur):
        """met a jour l'altitude Z du pion"""
        if valeur != self.z:
            self.z = valeur            

    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

    def supprimer(self):
        """'deconnecte' les items enfants avant de supprimer du pion"""
        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)
        self.text.prepareGeometryChange()
        self.text.setParentItem(None)
        self.plateau.removeItem(self)
        self.plateau = None
 
    ##################

    ###############   evenements clavier et souris    ##############
    #*EP
    def boundingRect(self):
        return QRectF()
    
    def hoverEnterEvent(self, event):
        """evenement lors du survol de la souris (en entree)"""
        #super(Pion, self).hoverEnterEvent(event)
        if (self.plateau.pionSelectionne() == None and self.plateau.modeActif == "standard") or self.plateau.modeActif == "pionSupprimer":
            self.surbrillance(True, 0.4)    
        self.plateau.pionSurvol(self.numero)
        event.ignore()

    def hoverLeaveEvent(self, event):
        """evenement lors du survol de la souris (en entree)"""
        #super(Pion, self).hoverLeaveEvent(event)
        self.surbrillance(False)
        self.plateau.pionSurvol(None)

    def mousePressEvent(self, event):
        """evenement lors du clic souris"""
        super(Pion, self).mousePressEvent(event)
        if event.button() == 1: #sur clic gauche
           accepte = self.plateau.pionClique(self.numero)
           if accepte: event.accept()
        else:
           event.ignore()

    def mouseDoubleClickEvent(self, event):
        """evenement lors du clic souris"""
        super(Pion, self).mouseDoubleClickEvent(event)
        if event.button() == 1: #sur clic gauche
           accepte = self.plateau.pionDoubleClic(self.numero)
           if accepte: event.accept()
        else:
           event.ignore()

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