// relations.c : definit le point d'entree pour l'application .
//
typedef int bool;
#define false 0
#define true -1

#include "stdlib.h"
#include "memory.h"
#include "stdio.h"
#include "string.h"

////////////////////////////////////////
// Exercice 1: Classement des Relations

typedef enum{
	FRERE = 2, COUSIN, PARENT, ONCLE, EPOUX, AMI, VIT, CONNAIT,
	CHEF, COLLEGUE, LOCATAIRE, TRAVAILLE, PROPRIETAIRE, SITUE, DECOUVERT
}rtype;

bool est_lien_parente(rtype id){
	return (id == FRERE || id == COUSIN || id == PARENT || id == ONCLE); 
}
bool est_lien_professionel(rtype id){
	return (id == CHEF || id == COLLEGUE); 
}
bool est_lien_connaissance(rtype id){
	return (id == EPOUX || id == AMI || id == CONNAIT || id == VIT);
}

typedef struct relations{
	char* leurRelation[17];
}RelationsTable;

RelationsTable* newRelationsTable(){
	RelationsTable* r = malloc(sizeof(RelationsTable));
	r->leurRelation[0] = "NULL";
	r->leurRelation[1] = "NULL";
	return r;
}
RelationsTable* addRelationsTable(RelationsTable* r, char* name, int id){ // name of their relation
	r->leurRelation[id] = name;
	return r;
}
RelationsTable* completeTheRelationsTable(){
	RelationsTable* r = newRelationsTable();
	char* n2 = " frère ou soeur de "; char* n3 = "cousin ou cousine de "; char* n4 = "père ou mère ";
	char* n5 = " oncle ou tante de "; char* n6 = "époux ou épouse de "; char* n7 = "ami de ";
	char* n8 = " vit avec "; char* n9 = " connait "; char* n10 = " supérieur de ";
	char* n11 = " collègue de "; char* n12 = " locataire de "; char* n13 = " travaille à ";
	char* n14 = " propriétaire de "; char* n15 = " situé à "; char* n16 = " découvert à ";
	char* table[15] = {n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16};
	for(int i=0; i<15; i++){
		r = addRelationsTable(r, table[i], i+2);
	}
	return r;
}

char* toStringRelation(rtype id){
	RelationsTable* r = completeTheRelationsTable();
	return r->leurRelation[id];
}

////////////////////////////////////////
// Exercice 2: Liste de pointeurs

typedef struct s_node{
	void *val;  // pointeur vers objet quelconque
	struct s_node *suiv;
}*listeg;

listeg listegnouv(){
	return NULL;
}
listeg adjtete(listeg lst, void *x){
	listeg new = malloc(sizeof(struct s_node));
	new->val = x;
	new->suiv = lst;
	return new;
}
listeg adjqueue(listeg lst, void *x){
	listeg new = malloc(sizeof(struct s_node));
	new->val = x;
	new->suiv = NULL;
	if( lst != NULL ){
		listeg copy = lst;
		while(copy->suiv != NULL){
			copy = copy->suiv; 
		}
		copy->suiv = new;
	}else{
		return new;
	}
	return lst;
}
listeg suptete(listeg lst){
	listeg deuxieme = lst->suiv;
	free(lst);
	return deuxieme;
}

void *tete(listeg lst){
	return lst->val;
}
int longueur(listeg lst){
	int res = 0;
	if( lst == NULL )
		return res;
	res++;
	listeg copy = lst;
	while(copy->suiv != NULL){
		copy = copy->suiv; 
		res++;
	}
	return res;
}
bool estvide(listeg lst){
	return lst == NULL;
}
void detruire(listeg lst){
	if( estvide(lst) )
		return;
	if(lst->suiv != NULL){
		free(lst);
		return;
	}
	listeg copy = lst;
	while(copy != NULL){
		listeg deathrowInmate = copy;
		copy = copy->suiv;
		free(lst);
	}
}
listeg rech(listeg lst, void *x, int(*comp)(void *, void *)){
	listeg copy = lst;
	while(copy != NULL){
		if( comp(x, copy->val) ){
			return lst;
		}else{
			copy = copy->suiv;
		}
	}
	return NULL;
}

////////////////////////////////////////
// Exercice 3: Construction du graphe

#define LONG_NOM_MAX 64
typedef enum{
	PERSONNE=1, OBJET, ADRESSE, VILLE
}etype;
typedef struct s_entite{
	char nom[LONG_NOM_MAX]; // le nom de l entite p.ex � Peugeot 106 �
	etype ident; // l identifiant associe, p.ex OBJET
}*Entite;
//3.1 les structures de donnees
typedef struct s_sommet{
	Entite uneEntite;
}*Sommet;

typedef struct s_arc{
	Sommet sommets[2]; // relation de sommet[0] avec sommet[1]
}*Arc;

typedef struct s_relations{
	// A DEFINIR
}*Relations;

//3.2 les constructeurs
Entite creerEntite(char *s, etype e){
	return NULL;
}
Sommet nouvSommet(Entite e){
	return NULL;
}
Arc nouvArc(Entite e, rtype type){
	return NULL;
}
void relationInit(Relations *g){
	
}
void relationFree(Relations *g){
	
}

//3.3 les comparaisons
int compEntite(void *e, void *string){
	return 0;
}
int compSommet(void *s, void *string){
	return 0;
}
int compArc(void *a, void *string){
	return 0;
}

//3.4 ajout d'entites et de relations
void adjEntite(Relations g, char *nom, etype t){
	
}
// PRE CONDITION: id doit �tre coh�rent avec les types des sommets correspondants � x et y
//                p.ex si x est de type OBJET, id ne peut pas etre une relation de parente
// PRE CONDITION: strcmp(nom1,nom2)!=0
void adjRelation(Relations g, char *nom1, char *nom2, rtype id){
	
}

////////////////////////////////////////
// Exercice 4: Explorer les relations entre personnes

// 4.1 listes de relations
listeg en_relation(Relations g, char *x){
	return NULL;
}
listeg chemin2(Relations g, char *x, char *y){
	return NULL;
}
// 4.2 verifier un lien de parente
// PRE CONDITION: strcmp(x,y)!=0
bool ont_lien_parente(Relations g, char *x, char *y){
	return false;
}

// 4.3 tester connaissances
// PRE CONDITION: les sommets correspondants � x et y sont de type PERSONNE
// PRE CONDITION: strcmp(x,y)!=0
bool se_connaissent(Relations g, char *x, char *y){
	return false;
}
// PRE CONDITION: les sommets correspondants � x et y sont de type PERSONNE
// PRE CONDITION: strcmp(x,y)!=0
bool se_connaissent_proba(Relations g, char *x, char *y){
	return false;
}
// PRE CONDITION: les sommets correspondants � x et y sont de type PERSONNE
// PRE CONDITION: strcmp(x,y)!=0
bool se_connaissent_peutetre(Relations g, char *x, char *y){
	return false;
}

////////////////////////////////////////
// Exercice 5: Affichages

void affichelg(listeg l, void(*aff)(void *)){
	
}

void afficheEntite(void *x){
	
}
void afficheArc(void *x){
	
}

////////////////////////////////////////
// Exercice 6: Parcours
void affiche_degre_relations(Relations r, char *x){
	
}


int main(){
	int i,j;
	
	printf("test toStringRelation(16) == %s \n", toStringRelation(16));
	printf("test est_lien_parente : %d   %d   %d \n",est_lien_parente(COUSIN),est_lien_parente(LOCATAIRE),
	est_lien_parente(EPOUX));
	printf("test est_lien_professionel : %d   %d   %d \n", est_lien_professionel(LOCATAIRE),
	est_lien_professionel(CHEF), est_lien_professionel(COLLEGUE));
	printf("test est_lien_connaissance : %d   %d   %d \n", est_lien_connaissance(AMI),
	est_lien_connaissance(CONNAIT), est_lien_connaissance(COLLEGUE));
	
	listeg liste = listegnouv();
	int x5 = 5, x4 = 4, x19 = 19, x3 = 3, x33 = 33;
	int *px5, *px4, *px19, *px3, *px33;
	px5 = &x5;   px4 = &x4;   px19 = &x19;   px3 = &x3;   px33 = &x33;
	int x0 = 0; int* px0 = &x0;
	liste = adjqueue(liste, &px5);
	liste = adjtete(liste, &px4);
	liste = adjqueue(liste, &px19);
	liste = adjtete(liste, &px3);
	liste = adjqueue(liste, &px33);
	liste = adjtete(liste, &px0);
	liste = suptete(liste);
	listeg copy = liste;
	for(int i=0; i<4; i++){
		printf("liste->val == %d \n", **(int**)copy->val);
		copy = copy->suiv;
	}
	printf("tete(liste) == %d \n", **(int**)tete(liste));
	detruire(liste);
	return 0;
	
	
	Relations r; relationInit(&r);
	// ajouter les entites de l'exemple
	char *tabe[] ={"KARL","LUDOVIC","CELINE","CHLOE","GILDAS","CEDRIC","SEVERINE",
		"PEUGEOT 106" ,"1, RUE DE LA RUE","STRASBOURG" };
	for (i = 0; i < 7; i++) 
		adjEntite(r, tabe[i], PERSONNE);
	adjEntite(r, tabe[7], OBJET);
	adjEntite(r, tabe[8], ADRESSE);
	adjEntite(r, tabe[9], VILLE);
	// ajouter les relations de l'exemple
	adjRelation(r, tabe[0], tabe[1], FRERE);
	adjRelation(r, tabe[0], tabe[2], AMI);
	adjRelation(r, tabe[0], tabe[3], CONNAIT);
	adjRelation(r, tabe[0], tabe[5], COUSIN);
	adjRelation(r, tabe[0], tabe[7], PROPRIETAIRE);
	adjRelation(r, tabe[0], tabe[8], PROPRIETAIRE);
	adjRelation(r, tabe[3], tabe[4], VIT);
	adjRelation(r, tabe[5], tabe[6], EPOUX);
	adjRelation(r, tabe[5], tabe[8], LOCATAIRE);
	adjRelation(r, tabe[7], tabe[8], DECOUVERT);
	adjRelation(r, tabe[8], tabe[9], SITUE);

	// explorer les relations
	printf("%s est en relation avec:\n", tabe[0]);
	affichelg(en_relation(r, tabe[0]),afficheArc);
	printf("\n");

	for (i = 0; i < 7; i++) for (j = i + 1; j < 10; j++)
	{
		printf("<%s> et <%s> ont les relations communes:\n", tabe[i], tabe[j]);
		listeg ch = chemin2(r, tabe[i], tabe[j]);
		affichelg(ch, afficheEntite);
		printf("\n");
		detruire(ch);
	}
	printf("\n\n");

	for (i = 0; i < 10; i++) for (j = i + 1; j < 10; j++)
	{
		printf("<%s> et <%s> ont lien de parente: %s\n",
			tabe[i], tabe[j], ont_lien_parente(r, tabe[i], tabe[j]) ? "vrai" : "faux");
	}
	printf("\n");
	for (i = 0; i < 7; i++)
	{
		for (j = i + 1; j < 7; j++)
		{
			printf("<%s> et <%s> se connaissent: %s\n",
				tabe[i], tabe[j], se_connaissent(r, tabe[i], tabe[j]) ? "vrai" : "faux");
			printf("<%s> et <%s> se connaissent tres probablement: %s\n",
				tabe[i], tabe[j], se_connaissent_proba(r, tabe[i], tabe[j]) ? "vrai" : "faux");
			printf("<%s> et <%s> se connaissent peut etre: %s\n",
				tabe[i], tabe[j], se_connaissent_peutetre(r, tabe[i], tabe[j]) ? "vrai" : "faux");
		}
		printf("\n");
	}

	affiche_degre_relations(r, tabe[3]);

	relationFree(&r);

	printf("\nPRESS RETURN\n");
	char buff[64]; fscanf(stdin, "%s", buff);
    return 0;
}