#include "lightbook.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

person *create_person(char *name, char *surname){
    /* Creazione */
    person *new = (person *)malloc(sizeof(person));
    new->name=strdup(name);
    new->surname=strdup(surname);
    new->nfriends=0;
    new->next=0; /* NULL */
    new->visited=0;
    return new;
}

person *insert_person(person *list, char *name, char *surname){
    /* Inserimento */
    person *new=create_person(name, surname);
    if (!list) return new;
    new->next=list;
    return new;
}

int insert_friend(person *p1, person *p2){
    if (p1->nfriends>=MAX || p2->nfriends>=MAX) return 1;
    p1->friends[p1->nfriends]=p2;
    p2->friends[p2->nfriends]=p1;
    p1->nfriends+=1;
    p2->nfriends+=1;
    return 0;
}

person *search(person *list, char *name, char *surname){
    if (!list) return 0;
    if (strcmp(list->name,name)==0 && strcmp(list->surname,surname)==0)
        return list;
    return search(list->next,name,surname);
}

void print(person *list){
    person *c;
    for(c=list; c!=NULL; c=c->next){
        printf("%s %s (%d)\n", c->name, c->surname, c->nfriends);
    }
}

void print_relation(person *p){
    /*! \TODO Implementare questa funzione... */
    int i;
    if (p->visited) return;
    p->visited=1; /* marca prima della visita degli amici! */
    printf("%s %s\n", p->name, p->surname);
    for(i=0; i<p->nfriends; i++)
        print_relation(p->friends[i]);
}

void reset_visit(person *list){
    if (!list) return;
    list->visited=0;
    reset_visit(list->next);
}

int remove_friend(person *p1, person *p2){
    /* remove p1 from friend list of p2 */
    int i, nf=p2->nfriends, pos=-1;
    for(i=0; i<nf; i++)
        if (p1==p2->friends[i]) {
            pos=i;
            break;
        }
    if (pos==-1) return 1;
    for(i=pos+1; i<nf; i++)
        p2->friends[i-1]=p2->friends[i];
    p2->nfriends=nf-1;
    return 0;
}

void free_person(person *p){
    free(p->name);
    free(p->surname);
    free(p);
}

person *del_person(person *list, person *p){
    if (!list) return 0;
    if (list==p) {
        person *new=p->next;
        free_person(p);
        return new;
    }
    list->next=del_person(list->next, p);
    return list;
}

person *delete_person(person *list, char *name, char *surname){
    person *rem = search(list, name, surname);
    int i;
    if (rem==0) return list;
    for(i=0; i<rem->nfriends; i++)
        remove_friend(rem, rem->friends[i]);
    return del_person(list, rem);
}

person *insert_in_order(person *list, person *p){
    person *cur, *old;
#ifdef DEBUG
    fprintf(stderr, "insert %s %s %p\n", p->surname, p->name, list);
#endif
    for(
            cur=list, old=NULL; 
            cur!=NULL;
            old=cur, cur=cur->next 
    ){
        int s=strcmp(cur->surname, p->surname);
        int n=strcmp(cur->name, p->name);
#ifdef DEBUG
        fprintf(stderr, "%s %s <> %s %s - %d %d \n", cur->surname, cur->name, p->surname, p->name, s, n);
#endif 
        if (s>0) break;
        if (s==0 && n>0) break;
    };
    if (old==NULL) {
            p->next=cur;
            return p;
    }
    old->next=p;
    p->next=cur;
    return list;
}

person *sort(person *list){
    person *head;
    person *tail;
    if (!list) return 0;
    head=list;
    tail=list->next;
#ifdef DEBUG
    fprintf(stderr, "head : %s %s\n", head->surname, head->name);
#endif 
    head->next=0;
    return insert_in_order(sort(tail), head);
}
