#include <stdlib.h>
#include <stdio.h>
#include <sybfront.h>
#include <sybdb.h>
#include <time.h>
#include "sybdbex.h"
#include "people.h"

#define OVERWRITE 1
#define kinBufLen 256
#define ksetEnivronErr 50
 
#ifdef BLIMP
#define interface "/usr/dbms/sybase/interfaces"
#define username ""
#define password ""
#define dbName "warehouse"
#define ENV_SYBASE "/usr/dbms/sybase"
#define ENV_DSLISTEN "warehouse"
#define ENV_DSQUERY "warehouse"
#else
#define interface "/dbms/testing/sybase/interfaces"
#define username "thorne"
#define password "foo"
#define dbName "vanguard_a"
#define ENV_SYBASE "/dbms/testing/sybase"
#define ENV_DSLISTEN "RPSSRVRA"
#define ENV_DSQUERY "RPSSRVRA"
#endif

struct person_ *target; 
/* Beginning of forward declarations */
void getPeopleFromTable(struct person_ **first, struct person_ **last);
float evaluation(struct person_ *person, struct person_ *target);
extern long  inProtocolParser(char inProtocol[], 
			      struct arguments_ *original,
			      struct arguments_ *normalized);
extern void debugPrint(char *format, ...);

/* End of forward declarations */
int main (argc, argv)
     int argc;
     char *argv[];
{
  struct arguments_ originalArguments, normalizedArguments;
  struct person_ *first, *last, *temp;
  unsigned long numOfRec, numOfBytes;
  char inProtocol[kinBufLen];
  long retCode;

  /* set environment */
  if (setEnvironment(OVERWRITE)==FAIL)
     genenrateErrTran(ksetEnvironErr);

  /* send banner */
  printf("You're connected to the people db.\n%s",EOM);
  fflush(stdout);
  
  /* get input protocol */
  scanf("%s", inProtocol);

  /* parse input protocol */
  if (retCode=inProtocolParser(inProtocol, &originalArguments, &normalizedArguments))
  {
    debugPrint("FAIL\n");
    genenrateErrTran(retCode);
  }

  first = last = NULL;
  target = (struct person_ *)malloc(sizeof(struct person_));
  if (!target)
  { 
/*    printf(msgMemoryError);*/
    return;
  } /* if (!target) */
  strcpy(target->lastName, normalizedArguments.lastName);
  strcpy(target->firstName, normalizedArguments.firstName);
  strcpy(target->middleName, normalizedArguments.middleName);
  strcpy(target->ssn, normalizedArguments.ssn);
  strcpy(target->dob, normalizedArguments.dob);
  printf("Before getPeopleFromTable time = %d\n", time(NULL));
  getPeopleFromTable(&first, &last);
  printf("After  getPeopleFromTable time = %d\n", time(NULL));
  temp = first;
  while(temp)
  {
    displayPerson(temp);
    temp = temp->next;
  }

  while (first)
  {
    temp = first->next;
    free(first);
    first = temp; 
  } 
  exit(STDEXIT); 
}

float evaluation(struct person_ *person, struct person_ *target)
{
  char personName[fullNameLength];
  char targetName[fullNameLength];
  char personInfo[ssnLength+dobLength+1];
  char targetInfo[ssnLength+dobLength+1];
  float namePercentage, infoPercentage, dobPercentage;
/*
  if (infoPercentage >= maybeMatch)
    return(infoPercentage);
*/
  strcpy(personName, person->lastName);
  strcat(personName, person->firstName);
  strcat(personName, person->middleName);
  strcpy(targetName, target->lastName);
  strcat(targetName, target->firstName);
  strcat(targetName, target->middleName);
  namePercentage = matchAlphaPercentage(personName, targetName);
  if (namePercentage >= maybeMatch)
    return(namePercentage);
  strcpy(personInfo, person->ssn);
  strcat(personInfo, person->dob);
  strcpy(targetInfo, target->ssn);
  strcat(targetInfo, target->dob);
  infoPercentage = matchDigitPercentage(personInfo, targetInfo);
  return((infoPercentage + namePercentage) /2);
}

void displayPerson(struct person_ *person)
{
  printf("%s, %s %s: %s %s; match percentage = %3.2f\n", 
         person->lastName, person->firstName,
         person->middleName, person->ssn, person->dob, person->matchScore);
}

void insertPerson
  (struct person_ *person, struct person_ **first, struct person_ **last)
{
  if (!*last)
  {
    *first = person;
    *last = person;
  } 
  else
    (*last)->next = person;
  person->next = NULL;
  person->prev = *last;
  *last = person;
}

void getPeopleFromTable(struct person_ **first, struct person_ **last)
{
  int counter = 0;
  float matchScore;
  struct person_ *person, *temp;
  DBPROCESS *dbprocess;
  DBCHAR lastName[lastNameLength+1];
  DBCHAR firstName[firstNameLength+1];
  DBCHAR middleName[middleNameLength+1];
  DBCHAR ssn[ssnLength+1];
  DBCHAR dob[dobLength+1];    
  LOGINREC *loginrec;
  RETCODE retcode;
  if (dbinit() == FAIL)
    exit(ERREXIT);
  dberrhandle(err_handler);
  dbmsghandle(msg_handler);
  dbsetifile(interface);
  loginrec = dblogin();
  DBSETLUSER(loginrec, username);
  DBSETLPWD(loginrec, password);
  dbprocess = dbopen(loginrec, NULL);
  dbuse(dbprocess, dbName);
  dbcmd(dbprocess, "select last_name, first_name, middle_name, ssn, ");
  dbcmd(dbprocess, "substring(convert(char(8), ");
  dbcmd(dbprocess, "datepart(year, date_of_birth) * 10000 + ");
  dbcmd(dbprocess, "datepart(month, date_of_birth) * 100 + ");
  dbcmd(dbprocess, "datepart(day, date_of_birth)), 5, 5) ");
  dbcmd(dbprocess, "from warehouse_person ");
  printf("Before dbsqlexec time = %d\n", time(NULL));
  dbsqlexec(dbprocess);
  printf("After  dbsqlexec time = %d\n", time(NULL));
  temp = (struct person_ *) malloc(sizeof(struct person_));
  if (!temp)
  {
    printf(msgMemoryError);
    return;
  }  /* if (!temp) */

  while ((retcode = dbresults(dbprocess)) != NO_MORE_RESULTS)
  {
    if (retcode == SUCCEED)
    {
      counter++;
  printf("Before dbbind time = %d\n", time(NULL));
     
      dbbind(dbprocess, 1, NTBSTRINGBIND, (DBINT)0, temp->lastName);
      dbbind(dbprocess, 2, NTBSTRINGBIND, (DBINT)0, temp->firstName);
      dbbind(dbprocess, 3, NTBSTRINGBIND, (DBINT)0, temp->middleName);
      dbbind(dbprocess, 4, NTBSTRINGBIND, (DBINT)0, temp->ssn);
      dbbind(dbprocess, 5, NTBSTRINGBIND, (DBINT)0, temp->dob);
  printf("After  dbbind time = %d\n", time(NULL));
  printf("Before match time = %d\n", time(NULL));

      while (dbnextrow(dbprocess) != NO_MORE_ROWS)
      {
        matchScore = evaluation(temp, target);
        if (matchScore > maybeMatch)
        {
          person = (struct person_ *) malloc(sizeof(struct person_));
          if (!person)
          {
            printf(msgMemoryError);
            return;
          }  /* if (!person) */
          strcpy(person->lastName, temp->lastName);
          strcpy(person->firstName, temp->firstName);
          strcpy(person->middleName, temp->middleName);
          strcpy(person->ssn, temp->ssn);
          strcpy(person->dob, temp->dob);
          person->matchScore = matchScore;
          insertPerson(person, first, last);
        } /* if (evaluateion() > maybeMatch) */
      } /* while (dbnextrow(dbprocess) != NO_MORE_ROWS) */
  printf("After  match time = %d\n", time(NULL));
    } /*    if (retcode == SUCCEED) */
  } /*  while ((retcode = dbresults(dbprocess)) != NO_MORE_RESULTS) */
/*  printf("Total Number of counter = %d\n", counter); */
  dbexit();
}

int setEnvironment(int overwrite)
{
  if (setenv("SYBASE", ENV_SYBASE, overwrite))
     return(FAIL);
  if (setenv("DSLISTEN", ENV_DSLISTEN, overwrite))
     return(FAIL);
  if (setenv("DSQUERY", ENV_DSQUERY, overwrite))
     return(FAIL);
  return(SUCCESS);
}

void generateErrTran(unsigned long errCode)
{
  debugPrint("The error code = %uld\n", errCode);
  exit(errCode);
}

