import unittest
import random

import names

from TP2.Objet import Objet
from TP2.Personnage import Personnage

words = open('/etc/dictionaries-common/words').readlines()


class VendreTest(unittest.TestCase):

    def test_vendre(self):
        random_objects1 = [Objet(random.choice(words), random.randint(1, 10)) for _ in range(5)]
        random_objects1_copy = random_objects1.copy()
        random_objects2 = [Objet(random.choice(words), random.randint(1, 10)) for _ in range(5)]
        random_objects2_copy = random_objects2.copy()

        p1 = Personnage(names.get_full_name(), random_objects1)
        p2 = Personnage(names.get_full_name(), random_objects2)

        o = random.choice(p1.getObjets())
        p2_objects = p2.getObjets().copy()

        richesse1 = p1.richesse
        richesse2 = p2.richesse

        self.assertTrue(p1.vendre(o, p2), "La méthode `Personnage.vendre` a échoué là où elle devait réussir")
        self.assertEqual(richesse1 + o.valeur, p1.richesse, f"La richesse du `Personnage` vendeur n'a pas augmenté de la valeur attendue {o.valeur}")
        self.assertEqual(richesse2 - o.valeur, p2.richesse, f"La richesse du `Personnage` acheteur n'a pas augmenté de la valeur attendue {o.valeur}")
        self.assertTrue(o not in p1.getObjets(), "L'`Objet` vendu n'a pas été enlevé de la liste des objets du vendeur")
        self.assertTrue(o in p2.getObjets(), "L'`Objet` acheté n'a pas été rajouté à la liste des objets de l'acquéreur")
        self.assertEqual(set(p2_objects + [o]), set(p2.getObjets()), "La nouvelle liste d'objets de l'acquéreur, n'est pas strictement égale a l'ancienne plus le nouvel objet (des objets manquent ou d'autres ont été ajoutés)")
        self.assertEqual(set(p1.getObjets() + p2.getObjets()), set(random_objects1_copy + random_objects2_copy), "Des objets ont disparu ou sont apparus de façon inattentdue")
        self.assertCountEqual(p1.getObjets() + p2.getObjets(), random_objects1 + random_objects2, "Le nombre d'objets total n'est pas resté constant")
        self.assertTrue(p2 in p1.amis, "L'acheteur n'a pas été ajouté aux amis du vendeur")
        self.assertEqual(0, p1.amis[p2], "Le niveau d'amitié envers l'acheteur n'est pas mis à 0 (lorsque l'acheteur n'était pas connu au préalable)")
        self.assertTrue(p1 in p2.amis, "Le vendeur n'a pas été ajouté aux amis de l'acheteur")
        self.assertEqual(0, p2.amis[p1], "Le niveau d'amitié envers le vendeur n'est pas mis à 0 (lorsque le vendeur n'était pas connu au préalable)")

        p1.amis[p2] = 0.13
        p2.amis[p1] = -0.87
        o = random.choice(p1.getObjets())
        self.assertTrue(p1.vendre(o, p2), "La méthode `Personnage.vendre` a échoué là où elle devait réussir")
        self.assertEqual(0.13, p1.amis[p2], "Le niveau d'amitié envers l'acheteur n'est pas resté inchangé (lorsque l'acheteur était connu au préalable)")
        self.assertEqual(-0.87, p2.amis[p1], "Le niveau d'amitié envers le vendeur n'est pas resté inchangé (lorsque le vendeur était connu au préalable)")

        p1_objects = p1.getObjets().copy()
        p2_objects = p2.getObjets().copy()

        self.assertFalse(p1.vendre(random.choice(p2_objects), p2), "La méthode `Personnage.vendre` a réussi là où elle devait échouer (vente d'objet pas dans sa possession)")
        self.assertEqual(p1.getObjets(), p1_objects, "Après une vente échouée, la liste des objets du vendeur n'est pas restée inchangée")
        self.assertEqual(p2.getObjets(), p2_objects, "Après une vente échouée, la liste des objets de l'acheteur n'est pas restée inchangée")


if __name__ == '__main__':
    unittest.main()
