/*  Listing 5 */
/*-----------------  PHLIST1.H ---------------*/
#include "arrylist.h"

typedef struct phone_entry {
    char last_name[21], first_name[11], phone_no[14];
} PHONE_ENTRY;

#define PHONE_LIST_CLASS ARRAY_LIST_CLASS \
			 PHONE_ENTRY *data; \
			 void (*sort)(struct phone_list *);

typedef struct phone_list {
    PHONE_LIST_CLASS
} PHONE_LIST;

PHONE_LIST *new_phone_list();
void destroy_phone_list(PHONE_LIST *);

/* ------------------ PHLIST1.C ----------------*/
#include "phlist1.h"
#include <string.h>
#include <conio.h>
#include <stdlib.h>

static void phone_list_memory_error(char *fun) {
    fprintf(stderr,
    "\nMemory Error in Function %s <Press a Key>\n", fun);
    getch(); exit(1);
}

static unsigned find(PHONE_LIST *this,char *srch_last_name){
    PHONE_ENTRY *pe;
    int orig;

    orig = this->curr;
    while(! this->at_end(this)) {
       pe = this->current(this);
       if ( stricmp(pe->last_name,srch_last_name) == 0)
          return(TRUE);
       else if (stricmp(pe->last_name,srch_last_name) > 0) {
          this->curr = orig;
          return(FALSE);
       }
       else
           this->next(this);
    }
    pe = this->current(this);
    if ( stricmp(pe->last_name,srch_last_name) == 0)
        return(TRUE);
    this->curr = orig;
    return(FALSE);
}

static display(PHONE_LIST *this) {
    PHONE_ENTRY *pe;

    pe = this->current(this);
    if (pe != NULL) {
        printf("%-20s, %-10s  -  %-13s\n", pe->last_name,
        pe->first_name, pe->phone_no);
    }
}

static void add_member(PHONE_LIST *this, PHONE_ENTRY *pe) {
    this->data = realloc(this->data,
    sizeof(PHONE_ENTRY) * (this->tot_members + 1));

    if (this->data == NULL)
       phone_list_memory_error("phone_list: add_member");

    memmove(this->data + this->tot_members, pe,
    sizeof(PHONE_ENTRY));
    ++(this->tot_members);
    this->sort(this);
}

static void replace_member(PHONE_LIST *this,
PHONE_ENTRY *pe){
 if (this->data != NULL)
   memmove(this->data + this->curr, pe,sizeof(PHONE_ENTRY));
}

static PHONE_LIST *current(PHONE_LIST *this) {
    if (! this->at_end(this) && this->data != NULL)
        return(this->data + this->curr);
     else
        return(NULL);
}

static int pe_comp(PHONE_ENTRY *pe1, PHONE_ENTRY *pe2) {
    int ret;
    ret = stricmp(pe1->last_name, pe2->last_name);
    if (ret == 0)
       return(stricmp(pe1->first_name, pe2->first_name));
    return(ret);
}

static sort(PHONE_LIST *this) {
    qsort(this->data, (size_t) this->tot_members,
    sizeof(PHONE_ENTRY),  pe_comp);
}

PHONE_LIST *new_phone_list() {
ARRAY_LIST *al;
PHONE_LIST *this;

al = new_array_list();
if (al == NULL)
       return(NULL);

this = calloc(1,sizeof(PHONE_LIST));
if (this == NULL) {
destroy_array_list(al);
    return(NULL);
}
memmove(this,al,sizeof(ARRAY_LIST));
free(al);

this->find = find; this->display = display;
this->add_member = add_member;
this->replace_member = replace_member;
this->current = current; this->sort = sort;
return(this);
}

void destroy_phone_list(PHONE_LIST *this) {
if (this->data)
   free(this->data);
destroy_array_list(this);
}
