/*
    Implementacja wzorcowego API aplikacji obsługującej wypożyczalnię DVD

    Ten plik zawiera definicje funkcji spełniających wymagania
    zawarte w API aplikacji obsługującej bazę danych wypożyczalni.
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "dvd.h"
#include "dvdc.h"

static void open_factory_error (CORBA_Object interface, 
				char *interfacename);
/* struktury CORBA */
static CORBA_Environment ev;
static CORBA_ORB orb;
static CORBA_Object dvd_client;
static DVD_MEMBERSHIP membership;
static DVD_TITLING titling;
static DVD_DISKS disks;
static DVD_RENTAL rental;
static DVD_RESERVATIONS reservations;
static DVD_UTILITIES utilities;

/* Ta funkcja zestawia połączenie z ORBit. */
   
#define IORLOCATION "../server/dvd-server.ior"
/* @interface ORB {
  CORBA_Environment ev;
  } */
/* - init_exception;   /* CORBA_exception_init(&ev); */
/* - init;             /* CORBA_ORB_init(&argc, argv, "orbit-local-orb", &ev); */
/* - strtoobj;         /* CORBA_ORB_string_to_object(orb, ior, &ev); */
/* - exception_id;     /* CORBA_exception_id(&ev)); */
/* - exception_value;  /* CORBA_exception_value(&ev)); */
/* - free_exception;   /* CORBA_exception_free(&ev); */
/* @end */

void ConnectORB (int argc, char *argv[]) {
  FILE *ifp; 
  char *ior;
  char filebuffer[1024];
  /* Start up the exception handler */
  CORBA_exception_init(&ev);  
  /* Request a connection to ORBit */ 
  orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", &ev);  
  ifp = fopen(IORLOCATION,"r");
  if( ifp == NULL ) {
    printf("No dvd-server.ior file!");
    exit(-1);
  }
  fgets(filebuffer,1024,ifp);
  printf("%s\n", filebuffer);
  ior = g_strdup(filebuffer);
  fclose(ifp);
  dvd_client = CORBA_ORB_string_to_object(orb, ior, &ev);
  if (!dvd_client) {
    printf("Cannot bind to IOR: %s\n", ior);
    exit(-1);
  }
}

/*  Logiczne wydaje się wstawienie w tym miejscu jakiejś weryfikacji
    bezpieczeństwa, aby udostępniać tylko te interfejsy, 
    do których dany użytkownik ma odpowiednie uprawnienia. */

/*  Dodamy "element kontroli autentyczności" jako argument każdej 
    z podanych tu funkcji. Egzemplarze interfejsów powinny więc 
    przestać działać, jeżeli serwer odmówi zwrotu odwołania
    do danego interfejsu. */

int Build_Factories(void) 
{
  /*  printf("Opening Factories...");  */
  membership = DVD_FACTORY_MEMBERSHIPFactory(dvd_client, &ev);
  open_factory_error(membership, "membership");
  if (ev._major != CORBA_NO_EXCEPTION) {
     printf("Got CORBA exception %d/%s\n", ev._major, 
       CORBA_exception_id(&ev));
    CORBA_exception_free(&ev);
    return DVD_ERR_CORBA_EXCEPTION;
  }
  titling = DVD_FACTORY_TITLINGFactory(dvd_client, &ev); 
  if (ev._major != CORBA_NO_EXCEPTION) {
     printf("Got CORBA exception %d/%s\n", ev._major, 
       CORBA_exception_id(&ev)); 
    CORBA_exception_free(&ev);
    return DVD_ERR_CORBA_EXCEPTION;
  }
  open_factory_error(titling, "titling");
  disks = DVD_FACTORY_DISKSFactory(dvd_client, &ev); 
  if (ev._major != CORBA_NO_EXCEPTION) {
    printf("Got CORBA exception %d/%s\n", ev._major, 
	   CORBA_exception_id(&ev));
    CORBA_exception_free(&ev);
    return DVD_ERR_CORBA_EXCEPTION;
  }
  open_factory_error(disks, "disks");
  rental = DVD_FACTORY_RENTALFactory(dvd_client, &ev); 
  if (ev._major != CORBA_NO_EXCEPTION) {
    printf("Got CORBA exception %d/%s\n", ev._major, 
	   CORBA_exception_id(&ev));
    CORBA_exception_free(&ev);
    return DVD_ERR_CORBA_EXCEPTION;
  }
  open_factory_error(rental, "rental");
  reservations = DVD_FACTORY_RESERVATIONSFactory(dvd_client, &ev); 
  if (ev._major != CORBA_NO_EXCEPTION) {
    printf("Got CORBA exception %d/%s\n", ev._major, 
	   CORBA_exception_id(&ev));
    CORBA_exception_free(&ev);
    return DVD_ERR_CORBA_EXCEPTION;
  }
  open_factory_error(reservations, "reservations");
  utilities = DVD_FACTORY_UTILITIESFactory(dvd_client, &ev); 
  if (ev._major != CORBA_NO_EXCEPTION) {
    printf("Got CORBA exception %d/%s\n", ev._major, 
	   CORBA_exception_id(&ev));
    CORBA_exception_free(&ev);
    return DVD_ERR_CORBA_EXCEPTION;
  }
  open_factory_error(utilities, "utilities");
  return DVD_SUCCESS;
}

int dvd_member_set(dvd_store_member *member)
{
  DVD_MEMBERSHIP_storemembers *memout;
  /*  printf("Set: dvd_store_member\n"); */
  if(member == NULL) {
    return DVD_ERR_NULL_POINTER;
  } else {
    memout= DVD_MEMBERSHIP_storemembers__alloc();
    memout->memberid = member->member_id;
    memout->memberno = member->member_no;
    memout->title = member->title;
    memout->fname = member->fname;
    memout->lname = member->lname;
    memout->houseflatref = member->house_flat_ref;
    memout->address1 = member->address1;
    memout->address2 = member->address2;
    memout->town = member->town;
    memout->state = member->state;
    memout->phone = member->phone;
    memout->zipcode = member->zipcode;
    DVD_MEMBERSHIP_set (membership, memout, &ev);
    if (ev._major != CORBA_NO_EXCEPTION) {
      printf("Got CORBA exception %d/%s\n", ev._major, 
	     CORBA_exception_id(&ev));
      return DVD_SUCCESS;
    }
  }
  return DVD_SUCCESS;
}

int dvd_member_get(int member_id, dvd_store_member *member)
{
  DVD_MEMBERSHIP_storemembers *cmember;
  int rc=0;
  if(member == NULL) {
    return DVD_ERR_NULL_POINTER;
  } else {
    DVD_MEMBERSHIP_get (membership, member_id, &cmember, &ev);
  }
  switch (ev._major) {
  case CORBA_NO_EXCEPTION: 
    rc = 0;
    break;
  case CORBA_SYSTEM_EXCEPTION:
    printf("Got CORBA exception %d/%d from DVD_MEMBERSHIP_get", 
	   ev._major,
	   (int) CORBA_exception_value(&ev));
    return DVD_ERR_NOT_FOUND;
    
  case CORBA_USER_EXCEPTION:
    printf("Error: %s\n", CORBA_exception_id(&ev));
    return DVD_ERR_NOT_FOUND;
  }
  if (rc != 0)   /* If we had an exception above... */
    return rc;
  /* If the retrieved member id is not as expected there
     may be an error, or the member may be deleted */
  if(member_id != cmember->memberid)
    return (int) DVD_ERR_NOT_FOUND;
  member->member_id = cmember->memberid; 
  strncpy(member->member_no, cmember->memberno, 6);
  strncpy(member->title, cmember->title, 4);
  strncpy(member->fname, cmember->fname, 26);
  strncpy(member->lname, cmember->lname, 26);
  strncpy(member->house_flat_ref, cmember->houseflatref, 26);
  strncpy(member->address1, cmember->address1, 51);
  strncpy(member->address2, cmember->address2, 51);
  strncpy(member->town, cmember->town, 51);
  strncpy(member->state, cmember->state, 3);
  strncpy(member->phone, cmember->phone, 31);
  strncpy(member->zipcode, cmember->zipcode, 11);
  /*  printf("Member: %d %s %s %s %s", member->member_id,
	 member->member_no, member->fname, member->lname,
	 member->zipcode); */
  return DVD_SUCCESS;
}

/* Make a new member record. The caller does not need to fill-in
   the member_id or member_no fields, these will be created before
   the member record is added to the database. The new meber_id
   is returned in the output parameter member_id. This must be
   use to retrieve the new member record to discover or set the
   member_no.
   */
int dvd_member_create(dvd_store_member *newrec, int *member_id)
{
  DVD_MEMBERSHIP_storemembers *memout;
  DVD_MEMBERSHIP_memberidt memberid;
  /*  printf("dvd_member_create\n"); */
  if(newrec == NULL)
    return DVD_ERR_NULL_POINTER;
  else {
    memout= DVD_MEMBERSHIP_storemembers__alloc();
    memout->memberid = newrec->member_id;
    memout->memberno = newrec->member_no;
    memout->title = newrec->title;
    memout->fname = newrec->fname;
    memout->lname = newrec->lname;
    memout->houseflatref = newrec->house_flat_ref;
    memout->address1 = newrec->address1;
    memout->address2 = newrec->address2;
    memout->town = newrec->town;
    memout->state = newrec->state;
    memout->phone = newrec->phone;
    memout->zipcode = newrec->zipcode;
  }
  /* Add the new member to the member and reservations file */
  DVD_MEMBERSHIP_create(membership, memout, &memberid, &ev);
  if (ev._major != CORBA_NO_EXCEPTION) {
    printf("Got CORBA exception %d/%s\n", ev._major, 
	   CORBA_exception_id(&ev));
    CORBA_exception_free(&ev); 
    return DVD_ERR_BAD_WRITE;
  }
  *member_id = memberid;
  return DVD_SUCCESS;
}

int dvd_member_delete(int member_id)
{
  DVD_MEMBERSHIP_memberidt m;
  int rc=0;
  /*  printf("dvd_member_delete %d\n", member_id); */
  m = member_id;
  DVD_MEMBERSHIP_delete(membership, m, &ev);
  /* Note that we've got about 4 lines of declarations and other "real
     code," and about 12 lines of "exception handling."  THIS is why
     exception handling in C is ugly */
  switch (ev._major) {
  case CORBA_NO_EXCEPTION: 
    return DVD_SUCCESS;
  case CORBA_SYSTEM_EXCEPTION:
    printf("Got CORBA exception %d/%d from DVD_MEMBERSHIP_delete", ev._major,
	   (int) CORBA_exception_value(&ev));
    rc = DVD_ERR_NOT_FOUND;
    break;
  case CORBA_USER_EXCEPTION:
    if (strcmp(ex_DVD_MEMBERSHIP_NOSUCHMEMBER, CORBA_exception_id(&ev)))
      rc = DVD_ERR_NOT_FOUND;
  }
  CORBA_exception_free(&ev); 
  return rc;
}

int dvd_member_get_id_from_number(char *member_no, int *member_id)
{
  int rc = 0;
  DVD_MEMBERSHIP_memberidt cmemberid;
  /*  printf("dvd_member_get_id_from_number %s\n", member_no); */
  DVD_MEMBERSHIP_idfromnumber(membership, member_no, &cmemberid, &ev);
  switch (ev._major) {
  case CORBA_NO_EXCEPTION:
    *member_id = cmemberid;
    CORBA_exception_free(&ev); 
    /*    printf("result: %d\n", cmemberid); */
    rc = DVD_SUCCESS;
    break;
  case CORBA_SYSTEM_EXCEPTION:
    printf("Got CORBA exception %d/%d from DVD_MEMBERSHIP_delete", ev._major,
	   (int) CORBA_exception_value(&ev));
    rc = DVD_ERR_NOT_FOUND;
    break;
  case CORBA_USER_EXCEPTION:
    if (strcmp(ex_DVD_MEMBERSHIP_NOSUCHMEMBER, CORBA_exception_id(&ev))) {
      /*      CORBA_exception_free(&ev);  */
      printf("NOSUCHMEMBER Exception - %s\n", CORBA_exception_id(&ev));
      rc = DVD_ERR_NOT_FOUND;
      break;
    } else {
      printf("OTHER USER Exception! - %s\n", CORBA_exception_id(&ev));
      rc= DVD_ERR_NOT_FOUND;
      break;
    }
  }
  CORBA_exception_free(&ev); 
  if (rc != 0) 
    return rc;
  return DVD_SUCCESS;
}

int dvd_member_search(char *lname, int *result_ids[], int *count)
{
  DVD_MEMBERSHIP_memberidList *CList;
  int *results = NULL, i, rc=0;
  DVD_MEMBERSHIP_search(membership, lname, &CList, &ev);
  /* printf("Found... %d\n", CList->_length); */
  if (ev._major != CORBA_NO_EXCEPTION) {
    printf("Got CORBA exception %d/%s\n", ev._major,
	   CORBA_exception_id(&ev));
    rc = DVD_ERR_NOT_FOUND;
  }
  
  /* printf("No exception... Got some results...  Count: %d\n", CList->_length); */
  /* Alternatively, there _were_ good results in CList->.. */
  results=calloc(CList->_length, sizeof(int));  /* Hopefully something
						   later free()s the
						   contents of
						   results[] */ 
  /* printf("Allocated memory...\n"); */
  if (results == NULL) {
    return DVD_ERR_NO_MEMORY;
  }
  /* printf("Search results: "); */
  for (i = 0; i < CList->_length; i++) {
    /* printf(" %d %d ", i, CList->_buffer[i]); */
    results[i] = CList->_buffer[i];
  }
  CList->_release = TRUE;
  *result_ids = results;
  *count = CList->_length;
  CORBA_free(CList);
  return DVD_SUCCESS;
}

int dvd_title_set(dvd_title *inttl)
{
  DVD_TITLING_dvdtitles *ttlout;
  if(inttl == NULL)
    return DVD_ERR_NULL_POINTER;
 
  ttlout= DVD_TITLING_dvdtitles__alloc();
  ttlout->titleid = inttl->title_id;
  ttlout->titletext =inttl->title_text;
  ttlout->asin =inttl->asin;
  ttlout->director =inttl->director;
  ttlout->genre =inttl->genre;
  ttlout->classification =inttl->classification;
  ttlout->actor1 =inttl->actor1;
  ttlout->actor2 =inttl->actor2;
  ttlout->rentalcost = inttl->rental_cost;
  ttlout->releasedate = inttl->release_date;
  ttlout->image = inttl->image_ref;

  DVD_TITLING_set(titling, ttlout, &ev);
  if (ev._major != CORBA_NO_EXCEPTION) {
    printf("Got CORBA exception %d/%s\n", ev._major, 
	   CORBA_exception_id(&ev));
    CORBA_exception_free(&ev); 
    return DVD_SUCCESS;
  }
  return DVD_SUCCESS;
}

int dvd_title_get(int title_id, dvd_title *ttlneeded)
{
  int rc = DVD_SUCCESS;
  DVD_TITLING_titlet ttlid;
  DVD_TITLING_dvdtitles *ttlin;

  if(ttlneeded == NULL)
    return DVD_ERR_NULL_POINTER;
  ttlid = title_id;
  DVD_TITLING_get(titling, ttlid, &ttlin, &ev);
  switch (ev._major) {
  case CORBA_NO_EXCEPTION: 
    rc = 0;
    break;
  case CORBA_SYSTEM_EXCEPTION:
    printf("Got CORBA exception %d/%d from DVD_TITLING_get", ev._major,
	   (int) CORBA_exception_value(&ev));
    rc = DVD_ERR_NOT_FOUND;
    break;
  case CORBA_USER_EXCEPTION:
    printf("Error: %s\n", CORBA_exception_id(&ev));
    rc = DVD_ERR_NOT_FOUND;
    break;
  }
  CORBA_exception_free(&ev); 
  if (rc != 0)   /* If we had an exception above... */
    return rc;
  /* If the retrieved title id is not as expected there
     may be an error, or the member may be deleted */
  if(title_id != ttlin->titleid)
    return (int) DVD_ERR_NOT_FOUND;
  
  ttlneeded->title_id =  ttlin->titleid;
  strncpy(ttlneeded->title_text,   ttlin->titletext, 61);
  strncpy(ttlneeded->asin,   ttlin->asin, 11);
  strncpy(ttlneeded->director,   ttlin->director, 51);
  strncpy(ttlneeded->genre,   ttlin->genre, 21);
  strncpy(ttlneeded->classification,   ttlin->classification, 11);
  strncpy(ttlneeded->actor1,   ttlin->actor1, 51);
  strncpy(ttlneeded->actor2,   ttlin->actor2, 51);
  strncpy(ttlneeded->rental_cost,   ttlin->rentalcost, 7);
  strncpy(ttlneeded->release_date,   ttlin->releasedate, 9);
  strncpy(ttlneeded->image_ref,   ttlin->image, 128);
  CORBA_free(ttlin);

  /* printf("Title: %d %s %s %s %s\n", ttlneeded->title_id,
	 ttlneeded->title_text, ttlneeded->director,
	 ttlneeded->genre, ttlneeded->classification); */
  return DVD_SUCCESS;
}

int dvd_title_create(dvd_title *newtitle, int *title_id)
{
  DVD_TITLING_dvdtitles *ctitle;
  DVD_TITLING_titlet cttlid;
  if (newtitle == NULL)
    return DVD_ERR_NULL_POINTER;
  ctitle = DVD_TITLING_dvdtitles__alloc();
  ctitle->titleid = newtitle->title_id;
  ctitle->titletext =newtitle->title_text;
  ctitle->asin =newtitle->asin;
  ctitle->director =newtitle->director;
  ctitle->genre =newtitle->genre;
  ctitle->classification =newtitle->classification;
  ctitle->actor1 =newtitle->actor1;
  ctitle->actor2 =newtitle->actor2;
  ctitle->rentalcost = newtitle->rental_cost;
  ctitle->releasedate = newtitle->release_date;
  ctitle->image = newtitle->image_ref;

  DVD_TITLING_create(titling, ctitle, &cttlid, &ev);
  CORBA_free(ctitle);
  if (ev._major != CORBA_NO_EXCEPTION) {
    printf("Got CORBA exception %d/%s\n", ev._major, 
	   CORBA_exception_id(&ev));
    CORBA_exception_free(&ev); 
    return DVD_SUCCESS;
  }
  return DVD_SUCCESS;
}

int dvd_title_delete(int title_id)
{
  DVD_TITLING_titlet t;
  int rc=0;
  /* printf("dvd_titling_delete %d\n", title_id); */
  t = title_id;
  DVD_TITLING_delete(titling, t, &ev);
  /* Note that we've got about 4 lines of declarations and other "real
     code," and about 12 lines of "exception handling."  THIS is why
     exception handling in C is ugly */
  switch (ev._major) {
  case CORBA_NO_EXCEPTION: 
    rc = DVD_SUCCESS;
    break;
  case CORBA_SYSTEM_EXCEPTION:
    printf("Got CORBA exception %d/%d from DVD_TITLING_delete", ev._major,
	   (int) CORBA_exception_value(&ev));
    rc = DVD_ERR_NOT_FOUND;
    break;
  case CORBA_USER_EXCEPTION:
    if (strcmp(ex_DVD_TITLING_NOSUCHTITLE, CORBA_exception_id(&ev)))
      rc = DVD_ERR_NOT_FOUND;
  }
  CORBA_exception_free(&ev); 
  return rc;
}

int dvd_title_search(char *title, char *name, int *result_ids[], int *count)
{
  DVD_TITLING_titleList *CList;
  int *results = NULL, i;
  DVD_TITLING_search(titling, title, name, &CList, &ev);
  /* printf("Found... %d\n", CList->_length); */
  if (ev._major != CORBA_NO_EXCEPTION) {
    printf("Got CORBA exception %d/%s\n", ev._major,
	   CORBA_exception_id(&ev));
    CORBA_exception_free(&ev); 
    return DVD_ERR_NOT_FOUND;
  }
  /* printf("No exception... Got some results...  Count: %d\n", CList->_length); */
  /* Alternatively, there _were_ good results in CList->.. */
  results=calloc(CList->_length, sizeof(int));
  /* printf("Allocated memory...\n"); */
  if (results == NULL) {
    return DVD_ERR_NO_MEMORY;
  }
  /* printf("Search results: "); */
  for (i = 0; i < CList->_length; i++) {
    /*    printf(" %d %d ", i, CList->_buffer[i]); */
    results[i] = CList->_buffer[i];
  }
  CList->_release = TRUE;
  *result_ids = results;
  *count = CList->_length;
  CORBA_free(CList);
  return DVD_SUCCESS;
}

int dvd_disk_set(dvd_disk *diskin)
{
  DVD_DISKS_dvddisks *cout;
  /* printf("Set: dvd_disk_set\n"); */
  if(diskin == NULL)
    return DVD_ERR_NULL_POINTER;
  else {
    cout= DVD_DISKS_dvddisks__alloc();
    cout->diskid = diskin->disk_id;
    cout->titleid = diskin->title_id;
    DVD_DISKS_set(disks, cout, &ev);
    if (ev._major != CORBA_NO_EXCEPTION) {
      printf("Got CORBA exception %d/%s\n", ev._major, 
	     CORBA_exception_id(&ev));
      return DVD_SUCCESS;
    }
  }
  return DVD_SUCCESS;
}

int dvd_disk_get(int disk_id, dvd_disk *diskout)
{
  DVD_DISKS_dvddisks cdisk;
  int rc=0;
  if(diskout == NULL) {
    return DVD_ERR_NULL_POINTER;
  } else {
    DVD_DISKS_get (disks, disk_id, &cdisk, &ev);
    /* printf ("Got DISK\n"); */
  }
  switch (ev._major) {
  case CORBA_NO_EXCEPTION:
    rc=0;
    break;
  case CORBA_SYSTEM_EXCEPTION:
    printf("Got CORBA exception %d/%d from DVD_DISKS_get", ev._major,
	   (int) CORBA_exception_value(&ev));
    rc= DVD_ERR_NOT_FOUND;
  case CORBA_USER_EXCEPTION:
    printf("Error: %s\n", CORBA_exception_id(&ev));
    rc = DVD_ERR_NOT_FOUND;
  }
  if (rc != 0) {   /* If we had an exception above... */
    return rc;
  }
  /* If the retrieved member id is not as expected there
     may be an error, or the member may be deleted */
  if(disk_id != cdisk.diskid)
    return (int) DVD_ERR_NOT_FOUND;
  diskout->disk_id = cdisk.diskid;
  diskout->title_id = cdisk.titleid;
  /* printf("Disk: %d %d", diskout->disk_id, diskout->title_id); */
  return DVD_SUCCESS;
}

int dvd_disk_create(dvd_disk *newdisk, int *disk_id)
{
  DVD_DISKS_dvddisks *cout;
  DVD_DISKS_dvdidt cdiskid;
  /* printf("dvd_disk_create\n"); */
  if(newdisk == NULL)
    return DVD_ERR_NULL_POINTER;
  else {
    cout= DVD_DISKS_dvddisks__alloc();
    cout->diskid = newdisk->disk_id;
    cout->titleid = newdisk->title_id;
  }
  /* Add the new member to the member and reservations file */
  DVD_DISKS_create(disks, cout, &cdiskid, &ev);
  if (ev._major != CORBA_NO_EXCEPTION) {
    printf("Got CORBA exception %d/%s\n", ev._major, 
	   CORBA_exception_id(&ev));
    CORBA_exception_free(&ev); 
    return DVD_SUCCESS;
  }
  *disk_id = cdiskid;
  CORBA_free(cout);
  return DVD_SUCCESS;
}

int dvd_disk_delete(int disk_id)
{
  DVD_DISKS_dvdidt c;
  int rc=0;
  /* printf("dvd_disk_delete %d\n", disk_id); */
  c = disk_id;
  DVD_DISKS_delete(disks, c, &ev);
  /* Note that we've got about 4 lines of declarations and other "real
     code," and about 12 lines of "exception handling."  THIS is why
     exception handling in C is ugly */
  switch (ev._major) {
  case CORBA_NO_EXCEPTION: 
    rc = DVD_SUCCESS;
    break;
  case CORBA_SYSTEM_EXCEPTION:
    printf("Got CORBA exception %d/%d from DVD_DISKS_delete", ev._major,
	   (int) CORBA_exception_value(&ev));
    rc = DVD_ERR_NOT_FOUND;
    break;
  case CORBA_USER_EXCEPTION:
    printf("Error: %s\n", CORBA_exception_id(&ev));
    rc = DVD_ERR_NOT_FOUND;
  }
  CORBA_exception_free(&ev); 
  return rc;
}

int dvd_disk_search(int title_id, int *result_ids[], int *count)
{
  DVD_DISKS_dvdList *CList;
  int *results = NULL, i;
  DVD_DISKS_search(disks, title_id, &CList, &ev);
  /* printf("Found... %d\n", CList->_length); */
  if (ev._major != CORBA_NO_EXCEPTION) {
    printf("Got CORBA exception %d/%s\n", ev._major,
	   CORBA_exception_id(&ev));
    CORBA_exception_free(&ev); 
    return DVD_ERR_NOT_FOUND;
  }
  CORBA_exception_free(&ev); 
  /* printf("No exception... Got some results...  Count: %d\n", CList->_length); */
  /* Alternatively, there _were_ good results in CList->.. */
  results=calloc(CList->_length, sizeof(int));
  /* printf("Allocated memory...\n"); */
  if (results == NULL) {
    return DVD_ERR_NO_MEMORY;
  }
  /* printf("Search results: "); */
  for (i = 0; i < CList->_length; i++) {
    /* printf(" %d %d ", i, CList->_buffer[i]); */
    results[i] = CList->_buffer[i];
  }
  CList->_release = TRUE;
  *result_ids = results;
  *count = CList->_length;
  CORBA_free(CList);
  return DVD_SUCCESS;
}

int dvd_rent_title(int member_id, int title_id, int *disk_id_to_rent)
{
  int rc=0;
  DVD_DISKS_dvdidt diskid;
  DVD_RENTAL_renttitle(rental, member_id, title_id, &diskid, &ev);
  switch (ev._major) {
  case CORBA_NO_EXCEPTION: 
    rc = 0;
    break;
  case CORBA_SYSTEM_EXCEPTION:
    printf("Got CORBA exception %d/%d from DVD_DISKS_delete", 
	   ev._major, (int) CORBA_exception_value(&ev));
    rc = DVD_ERR_NOT_FOUND;
    break;
  case CORBA_USER_EXCEPTION:
    /* We could check for a number of different exceptions, but
       frankly, since all we return with is DVD_ERR_NOT_FOUND, there's
       not much point to checking... */
    printf("Error: %s\n", CORBA_exception_id(&ev));
    rc = DVD_ERR_NOT_FOUND;
  }
  CORBA_exception_free(&ev); 
  if (rc != 0)
    return rc;
  *disk_id_to_rent = diskid;
  return DVD_SUCCESS;
}

int dvd_rented_disk_info(int disk_id, int *member_id, char *date_rented)
{
  DVD_MEMBERSHIP_memberidt memberid;
  DVD_datec daterented;
  int rc=0;
  DVD_RENTAL_rentdiskinfo(rental, disk_id, &memberid, &daterented,
			  &ev);
  switch (ev._major) {
  case CORBA_NO_EXCEPTION: 
    rc = 0;
    *member_id = memberid;
    strcpy(date_rented, daterented);
    CORBA_free(daterented);
    break;
  case CORBA_SYSTEM_EXCEPTION:
    printf("Got CORBA exception %d/%d from DVD_RENTAL_rentdiskinfo", 
	   ev._major, (int) CORBA_exception_value(&ev));
    rc = DVD_ERR_NOT_FOUND;
    break;
  case CORBA_USER_EXCEPTION:
    printf("Error: %s\n", CORBA_exception_id(&ev));
    rc = DVD_ERR_NOT_FOUND;
  }
  CORBA_exception_free(&ev);
  if (rc != 0) 
    return rc;
  return DVD_SUCCESS;
}

int dvd_disk_return(int disk_id, int *member_id, char *date)
{
  int rc = 0;
  DVD_MEMBERSHIP_memberidt memberid;
  if(date == NULL)
    return DVD_ERR_NULL_POINTER;
  DVD_RENTAL_diskreturn(rental, disk_id, date, &memberid, &ev);
  switch (ev._major) {
  case CORBA_NO_EXCEPTION: 
    rc = 0;
    *member_id = memberid;
    break;
  case CORBA_SYSTEM_EXCEPTION:
    printf("Got CORBA exception %d/%d from DVD_RENTAL_rentdiskinfo", 
	   ev._major, (int) CORBA_exception_value(&ev));
    rc = DVD_ERR_NOT_FOUND;
    break;
  case CORBA_USER_EXCEPTION:
    printf("Error: %s\n", CORBA_exception_id(&ev));
    rc = DVD_ERR_NOT_FOUND;
  }
  CORBA_exception_free(&ev);
  if (rc != 0)
    return rc;
  return DVD_SUCCESS;
}

int dvd_reserve_title(char *date, int title_id, int member_id)
{
  int rc=0;
  if (date == NULL)
    return DVD_ERR_NULL_POINTER;
  DVD_RESERVATIONS_reservetitle(reservations, date, title_id,
				member_id, &ev);
  switch (ev._major) {
  case CORBA_NO_EXCEPTION: 
    rc = 0;
    break;
  case CORBA_SYSTEM_EXCEPTION:
    printf("Got CORBA exception %d/%d from DVD_RESERVATIONS_reservetitle", 
	   ev._major, (int) CORBA_exception_value(&ev));
    rc = DVD_ERR_NOT_FOUND;
    break;
  case CORBA_USER_EXCEPTION:
    printf("Error: %s\n", CORBA_exception_id(&ev));
    rc = DVD_ERR_NOT_FOUND;  /* No more intelligent response than this... */
  }
  CORBA_exception_free(&ev);
  if (rc != 0)
    return rc;
  return DVD_SUCCESS;
}

int dvd_reserve_title_cancel(int member_id)
{
  int rc = 0;
  DVD_RESERVATIONS_cancelreservation(reservations, member_id, &ev);  
  switch (ev._major) {
  case CORBA_NO_EXCEPTION: 
    rc = 0;
    break;
  case CORBA_SYSTEM_EXCEPTION:
    printf("Got CORBA exception %d/%d from DVD_RESERVATIONS_cancelreservation", 
	   ev._major, (int) CORBA_exception_value(&ev));
    rc = DVD_ERR_NOT_FOUND;
    break;
  case CORBA_USER_EXCEPTION:
    printf("Error: %s\n", CORBA_exception_id(&ev));
    rc = DVD_ERR_NOT_FOUND;  /* No more intelligent response than this... */
  }
  CORBA_exception_free(&ev);
  if (rc != 0)
    return rc;
  return DVD_SUCCESS;
}

int dvd_reserve_title_query_by_member(int member_id, int *title_id)
{
  int rc=0;
  DVD_TITLING_titlet titleid;
  DVD_RESERVATIONS_queryreservationbymember (reservations, member_id,
					     &titleid, &ev);
  switch (ev._major) {
  case CORBA_NO_EXCEPTION: 
    rc = 0;
    *title_id = titleid;
    return DVD_SUCCESS;
  case CORBA_SYSTEM_EXCEPTION:
    printf("Got CORBA exception %d/%d from DVD_RESERVATIONS_queryreservationbymember", 
	   ev._major, (int) CORBA_exception_value(&ev));
    rc = DVD_ERR_NOT_FOUND;
    break;
  case CORBA_USER_EXCEPTION:
    printf("Error: %s\n", CORBA_exception_id(&ev));
    rc = DVD_ERR_NOT_FOUND;  /* No more intelligent response than this... */
  }
  CORBA_exception_free(&ev);
  if (rc != 0)
    return rc;
  return DVD_SUCCESS;
}

int dvd_reserve_title_query_by_titledate(int title_id, char *date, int
					 *member_ids[])  
{
  /* Return a list of members who have reserved this title on this date */
  /* Not yet implemented... */
  return DVD_ERR_NOT_FOUND;
}

int dvd_overdue_disks(char *date1, char *date2, int *disk_ids[], int *count)
{
  /* Not yet implemented ... */
  return DVD_ERR_NOT_FOUND;
}

int dvd_get_genre_list(char **genre_list[], int *count)
{
  DVD_TITLING_genreList *cgenrelist;
  cgenrelist =  DVD_TITLING_genreList__alloc();
  DVD_UTILITIES_getgenres (utilities, &cgenrelist, &ev);
  if (ev._major != CORBA_NO_EXCEPTION) {
    printf("Got CORBA exception %d/%s\n", ev._major, 
	   CORBA_exception_id(&ev));
    return DVD_SUCCESS;
  }
  *genre_list = cgenrelist->_buffer;
  *count = cgenrelist->_length;
  return DVD_SUCCESS;
}

int dvd_get_classification_list(char **class_list[], int *count)
{
  int i;
  DVD_TITLING_classList *cclasslist;
  DVD_UTILITIES_getclassifications (utilities, &cclasslist, &ev);
  if (ev._major != CORBA_NO_EXCEPTION) {
    printf("Got CORBA exception %d/%s\n", ev._major, 
	   CORBA_exception_id(&ev));
    return DVD_SUCCESS;
  }
  /* printf ("dvd_get_classification_list...\n");
     for (i = 0; i < cclasslist->_length; i++) {
       printf ("Item %d: %s\n", i, cclasslist->_buffer[i]);
     } */
  *class_list = cclasslist->_buffer;
  *count = cclasslist->_length;
  return DVD_SUCCESS;
}

int dvd_err_text(int err_number, char **message_to_show)
{
  static char default_msg[80];
  CORBA_char *errmsg;
  /* printf("Getting error for [%d]\n", err_number); */
  DVD_UTILITIES_errortext(utilities, err_number,  &errmsg, &ev);
  if (ev._major != CORBA_NO_EXCEPTION) {
    printf("Got CORBA exception %d/%s\n", ev._major, 
	   CORBA_exception_id(&ev));
    return DVD_SUCCESS;
  }
  strcpy(default_msg, errmsg);
  *message_to_show = default_msg;
  return DVD_SUCCESS;
}
 
int dvd_today(char **date)
{
  static char today[9];
  DVD_datec c_today;
  DVD_UTILITIES_today(utilities, &c_today, &ev);
  if (ev._major != CORBA_NO_EXCEPTION) {
    printf("Got CORBA exception %d/%s\n", ev._major, 
	   CORBA_exception_id(&ev));
    return DVD_SUCCESS;
  }
  strcpy (today, c_today);
  *date = today; 
  return DVD_SUCCESS;
}

static void open_factory_error (CORBA_Object interface, char *interfacename) {
  if (!interface) {
    printf ("Could not bind factory for interface %s", interfacename);
  }
}
int dvd_open_db()
{
  /* printf("Open DB...\n"); */
  return Build_Factories();
}

int dvd_close_db(void)
{
  return 0;
}
