# !ATENTION! Il manque un s à self.sommets dans la méthode transformer,
# sinon il n'y a pas de modification en place

from Sommet_correction import Sommet
from Face import Face
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection


class Objet3D:

    """
    Représente un objet 3D composé de sommets, de faces et d'un nom.
    """

    def __init__(self):
        """
        Initialise un objet 3D vide.
        """
        self.sommets = []
        self.faces = []
        self.nom = ""

    def ajouter_sommet(self, x, y, z):
        """
        Ajoute un sommet à l'objet 3D.
        """
        self.sommets.append(Sommet(x, y, z))

    def ajouter_face(self, liste_sommets):
        """
        Ajoute une face à l'objet 3D.
        """
        self.faces.append(Face(liste_sommets))

    def __str__(self):
        """
        Renvoie une représentation textuelle de l'objet 3D.
        """
        return str({'nom': self.nom, 'sommets': len(self.sommets), 'faces': len(self.faces)})

    def afficher(self):
        """
        Affiche l'objet 3D à l'aide de matplotlib.
        """
        fig = plt.figure()
        ax = fig.add_subplot(111, projection='3d')

        f = []
        for face in self.faces:
            print(face.sommets) # Print en trop ?
            x = [(self.sommets[s-1].x, self.sommets[s-1].y, self.sommets[s-1].z)
                 for s in face.sommets]
            f.append(x)
        mesh = Poly3DCollection(f, alpha=0.4, edgecolor='black')
        ax.add_collection3d(mesh)
        plt.show()

#############################################################################
# Méthode à modifier de la question 5                                       #
#############################################################################
    def transformer(self, rapport):
        """
        Applique une transformation d'échelle à l'objet 3D en modifiant directement ses sommets.
        """
        sommets = []
        for sommet in self.sommets:
            sommets.append(
                Sommet(sommet.x*rapport, sommet.y*rapport, sommet.z*rapport))
        # manque un s à self.sommets dans la version de base, 
        # sinon il n'y a pas de modification en place
        # self.sommets = sommets
        
        nouv_obj = Objet3D()
        nouv_obj.sommets = sommets
        # les faces ne sont pas modifiées par la transformation d'échelle
        # C'est un choix discutable : pour bien "séparer" les objets, il est 
        # préférable de faire une copie des faces plutôt que de les partager
        # entre les deux objets
        
        # nouv_obj.faces = self.faces
        
        # ou 
        
        nouv_obj.faces = []
        for face in self.faces:
            nouv_obj.faces.append(Face(face.sommets))
        
        nouv_obj.nom = self.nom + "_transforme"
        return nouv_obj


#############################################################################
# Écrire le code de la méthode trouver_sommets_adjacents de la question 2   #
#############################################################################

    def trouver_sommets_adjacents(self, sommet):
        """
        Trouve deux sommets adjacents dans l'objet 3D s'il en existe.
        """
        for s1 in self.sommets:
            for s2 in self.sommets:
                if s1.est_adjacent(s2):
                    return s1, s2
        return None

#############################################################################
# Programme pour tester votre méthode de la question 2                      #
#############################################################################

# Premier test : les sommets sont adjacents

objet = Objet3D()
objet.ajouter_sommet(0, 0, 0)  # s1
objet.ajouter_sommet(1, 0, 0)  # s2

res = objet.trouver_sommets_adjacents(objet.sommets[0])
assert res is not None
s1, s2 = res

assert (s1.x, s1.y, s1.z) == (0, 0, 0)
assert (s2.x, s2.y, s2.z) == (1, 0, 0)

# Second test : les sommets ne sont pas adjacents

objet2 = Objet3D()
objet2.ajouter_sommet(1, 0, 0)  # s2
objet2.ajouter_sommet(0, 1, 0)  # s3
objet2.ajouter_sommet(0, 0, 1)  # s4

res = objet2.trouver_sommets_adjacents(objet2.sommets[0])
assert res is None