#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "list.h"

void remove_blanks(){
    int c;
    /* get rid of blank characters */
    while(isspace(c = getchar()));

    /* put back the one that wasn't blank */
    ungetc(c, stdin);
}

int safe_gets(char *s, int length){
    int i, c;

    /* get rid of blankc at the beginning */
    while(isspace(c = getchar()));
    ungetc(c, stdin);
    
    for(i = 0; i < length - 1; i++){
	/* read one char at a time */
	c = getchar();
	if(c == '\n') /* stop reading if you got a newline */
	    break;
	else{
	    /* copy characters into the buffer */
	    s[i] = (char) c;
	}
    }

    /* finish the string off with a NULL terminator */
    s[i] = '\0';

    return i;
}

node * get_from_stdin(){
    node *newnode;
    char c;
    int age;

    newnode = (node *) calloc(sizeof(node), 1);

    newnode->age = 0;
    newnode->sex = undefined;
    newnode->prev = NULL;
    newnode->next = NULL;

    /* first get the gender from user*/
    printf("NEW NODE ENTRY\n");
    do {
	    printf("Please enter gender (m/f)\n");

	    c = getchar();

	    switch (c){
	        case 'm':
		case 'M':
		    newnode->sex = male;
    		    break;
		case 'f':
		case 'F':
    		    newnode->sex = female;
    		    break;
		default:
    		    printf("Input error: gender %c not known.\n", c);
    		    break;
	   }
    } while (newnode->sex == undefined);

    /* next get age */
    do {
	printf("Please enter age:\n");
    	if(scanf("%d", &newnode->age) != 1)
    	    printf("Input error. Please try again.\n");
    
    } while (newnode->age == 0);

    /* Entrando com o nome */
    printf("Please enter name:\n");
    remove_blanks();
    safe_gets(newnode->name, MAX_NAME);

    return newnode;
}

node *find_insert_position(node *list, node *item){
    /* if male or list is empty, item is appended */
    if(list == NULL || item->sex == male)
	return NULL;

    /* if female, find the younger woman or first man */
    while(list->age > item->age && list->sex == female && list != NULL){
    	list = list->next;
    }
    return list;
}

/* inserts item into list at position pos
 * if pos is null, the item is appended to the list */
void insert_node(node **list_start, node **list_end, node *item, node *pos){

    /* if this is the first node*/
    if(*list_start == NULL){
	*list_start = item;
        *list_end = item;
    }
    else if(pos == NULL){ /* append to list*/
	pos = *list_start;
	/*get to the end of list*/
	while(pos->next != NULL)
	    pos = pos->next;
	
	/* append the item */
	pos->next = item;
    	item->prev = pos;
        *list_end = item;
	return;

    } else{ /* insert */
	item->prev = pos->prev;
	item->next = pos;
	pos->prev = item;
	if(item->prev != NULL)
	    item->prev->next = item;
	else /* it is the first element, we need to update list */
	    *list_start = item;
    }
}

void dump_node(node *item){
    if(item->sex == female)
	    printf("female ");
    else
	    printf("  male ");
	
    printf("%d  %s\n", item->age, item->name);

}

void print_list(node *list){
    while(list != NULL){
    	dump_node(list);
    	list = list->next;
    }
}

void purge_list(node *list){
    if(list == NULL)
	return;

    node * freed = list;
    list = list->next;
    while(list != NULL){
    	list = list->next;
    	freed = freed->next;
    	free(freed->prev);
    }
    free(freed);
}

int main(int argc, char **argv){
    node *list_start = NULL;
    node *list_end = NULL;
    node *new_item = NULL;
    int choice;
    do{
    	printf("options:\n");
    	printf(" 1 - add new item\n 2 - print list\n 3 - reset\n 4 - exit\n");
    	if(scanf("%d", &choice) == 1){
	    /* remove the lf left there by scanf */
	    getchar();
    	    switch (choice){
    		case 1:
		    new_item = get_from_stdin();
    		    insert_node(&list_start, &list_end, new_item, 
				find_insert_position(list_start, new_item));
    		    break;
    		case 2:
    		    print_list(list_start);
    		    break;
    		case 3:
    		    purge_list(list_start);
    		    list_start = NULL;
                list_end = NULL;
    		    break;
    		case 4:
    		    return 0;
    		default:
    		    printf("Bad input. Please try again.\n");
	        }
    	}
    } while(1);
    return 0;
}
