/**
 * \file Personne3.cpp
 * \brief On implémente les différentes fonctions et méthodes définies dans les fichiers d'en-tête. La compilation de ce fichiers .cpp nous permettra d'utiliser dans le main ces fonctions
Il inclut les définitions à partir d'un en-tête.
 * \author Matis MAZINGUE Joan PIERRON Maxence LANONE Hugo PRADIER G7
 * \date 31 Mars 2022
 */

#include "Personne3.hpp"
#include "Contact3.hpp"

#include <iostream>
#include <unordered_set>
#include <queue>

using namespace std;
using namespace reseau2;

// #define TECHNIQUE_A

/**
 * @brief Construct a new Personne:: Personne object
 * 
 * @param prenom 
 */
Personne::Personne(const std::string& prenom):prenom{prenom}{
// #ifdef TECHNIQUE_A
	contacts = new ListeContact{};
// #else
// 	contacts = new Conteneur{};
// #endif
}

/**
 * @brief 
 * 
 * @return const string& 
 */
const string& Personne::getPrenom() const{
	return this->prenom;
}

/**
 * @brief 
 * 
 * @param personne 
 */
void reseau2::Personne::ajtContact(const Personne &personne) {
	this->contacts->ajtContact(personne);
}

/**
 * @brief Destroy the Personne:: Personne object
 * 
 */
Personne::~Personne() {
	delete contacts;
}

/**
 * @brief 
 * 
 * @param p 
 * @return true 
 * @return false 
 */
bool Personne::peutCommuniquerA(const Personne &p) const {
	unordered_set<const Personne*> visited;
	queue<const Personne*> file;
	file.push(this);
	while (!file.empty()) {
		const Personne* front = file.front();
		file.pop();
		for (const Personne* perso : front->contacts->getValue()) {
			if (perso == &p) {
				cout << this->prenom << " peut communiquer avec " << p.getPrenom() << "\n";
				return true;
			}
			else if (visited.find(perso) == visited.end()) {
				file.push(perso);
				visited.insert(perso);
			}
		}
	}
	cout << this->prenom << " ne peut pas communiquer avec " << p.getPrenom() << "\n";
	return false;
}

