/*
 * This is an example of how to make a high-level client
 */

#include <sr-util.h>
#include <sr-logger.h>
#include <high/client-structdesc.h>

#define DATABASE	"ubobok"
#define RESULTSETID	"new"
#define SEARCH		"harstad"
#define CLIENTSERVER	"gandalf.uio.no"
#define SRSERVER	"bombur"

/*
 * Prototypes
 */

void printDiagRec (HlvlDiagRec *diag);

void main()
{
  HC_Packet *pk;
  int ref;

  facLogLevel(facAll, llevTrace);
  facLogLevel(facStruct, llevDebug);

  if ( HC_Initialise() == False)
  {
    printf("Failed to open connection to high-level client-server.\n");
    exit(1);
  }

  pk = HC_AllocPacket(hcOpenRequest, 0);
  pk->u.open_request->address = (char *) strdup(SRSERVER);
  pk->u.open_request->preferredMessageSize = 2048;
  pk->u.open_request->maximumMessageSize = 65536;
  pk->u.open_request->authentification = (char *) NULL;
  pk->u.open_request->userInformationField = (char *) NULL;

  if (HC_Send(pk) == False)
  {
    printf("Failed to send hcOpenRequest to high-level client-server.\n");
    exit(1);
  }
  ref = pk->ref;
  HC_FreePacket(pk);
    
  if (HC_Receive(&pk) == False)
  {
    printf("Failed to receive packet.\n");
    exit(1);
  }
  if (pk->type != hcOpenResponse || pk->u.open_response->openAccepted != True)
  {
    printf("Failed to receive open connection.\n");
    exit(1);
  }
  printf("Connection opened.\n");

  pk = HC_AllocPacket(hcSearchRequest, ref);
  pk->u.search_request->smallSetUpperBound = 10;
  pk->u.search_request->largeSetLowerBound = 100;
  pk->u.search_request->mediumSetPresentNumber = 10;
  pk->u.search_request->replaceIndicator = False;
  pk->u.search_request->proposedResultSetId = strdup(RESULTSETID);
/*
 * You don't have to set all pointers to NULL, since calloc() is used in
 * HC_AllocPacket().
 */
  pk->u.search_request->smallSetRecordComposition = (RecordComposition *) malloc(sizeof(RecordComposition));
  pk->u.search_request->smallSetRecordComposition->genericRecordComposition = True;
  pk->u.search_request->smallSetRecordComposition->u.generic = strdup("F");
  pk->u.search_request->mediumSetRecordComposition = (RecordComposition *) malloc(sizeof(RecordComposition));
  pk->u.search_request->mediumSetRecordComposition->genericRecordComposition = True;
  pk->u.search_request->mediumSetRecordComposition->u.generic = strdup("B");
  pk->u.search_request->preferredRecordSyntax = strdup("RECORDSYNTAX NORMARC");
  pk->u.search_request->databaseNames = (DatabaseName *) malloc(sizeof(DatabaseName));
  pk->u.search_request->databaseNames->database = strdup(DATABASE);
  pk->u.search_request->databaseNames->next = (DatabaseName *) NULL;
  pk->u.search_request->query = (Query *) malloc(sizeof(Query));
  pk->u.search_request->query->kind = queryIso8777Query;
  pk->u.search_request->query->q.iso8777Query = (octetString *) malloc(sizeof(octetString));
  pk->u.search_request->query->q.iso8777Query->value = strdup(SEARCH);
  pk->u.search_request->query->q.iso8777Query->len = strlen(SEARCH);
 
  if (HC_Send(pk) == False)
  {
    printf("Failed to send hcSearchRequest.\n");
    exit(1);
  }
  HC_FreePacket(pk);
  if (HC_Receive(&pk) == False)
  {
    printf("Failed to receive packet.\n");
    exit(1);
  }
  if (pk->type != hcSearchResponse)
  {
    printf("Failed to receive hcSearchResponse.\n");
    exit(1);
  }
  if (pk->u.search_response->searchStatus == False)
  {
    printf("Found no records.\n");
    exit(0);
  }
  printf("%d matches, %d records returned.\n",
         pk->u.search_response->numberOfRecordsFound,
         pk->u.search_response->numberOfRecordsReturned);
  if (pk->u.search_response->numberOfRecordsReturned == 0)
    exit(0);
  if (pk->u.search_response->presentStatus == False)
  {
    printf("Failed to present records.\n");
    /* exit(1); */
  }
  switch(pk->u.search_response->records->recKind)
  {

  case recHlvlNamePlusRecord:
    {
    HlvlNamePlusRecord *rec;
      for (rec = pk->u.search_response->records->u.databaseOrSurDiagnostics;
           rec != (HlvlNamePlusRecord *) NULL; rec = rec->next)
      {
        switch(rec->recKind)
        {
        case recHlvlRecord:
          printf("%s\n",rec->u.record.databaseRecord.value);
          break;
        case recHlvlSurrogateDiagRec:
          printf("Surrogate Diagnostic:\n");
          printDiagRec(rec->u.surrogateDiagnostic);
          break;
        }
      }
      break;
    }
  case recHlvlNonSurrogateDiagRec:
    printf("Nonsurrogate Diagnostic:\n");
    printDiagRec(pk->u.search_response->records->u.nonSurrogateDiagnosticRecord);
    break;
  }

  pk = HC_AllocPacket(hcCloseRequest, ref);
  if (HC_Send(pk) == False)
  {
    printf("Failed to send close request.\n");
    exit(1);
  }
  HC_FreePacket(pk);

  if (HC_Receive(&pk) == False)
  {
    printf("Failed to receive close response.\n");
    exit(1);
  }

  printf("Close was %saccepted.\n",
         pk->u.close_response->closeAccepted == True ? "" : "not ");
  if (pk->u.close_response->message)
    printf("Close message: %s\n", pk->u.close_response->message);
  HC_FreePacket(pk);

  if (HC_Close() == False)
  {
    printf("Failed to close connection.\n");
    exit(1);
  }
  printf("Closed connection.\n");
}

void
printDiagRec (HlvlDiagRec *diag)
{
  printf("Diagnostic: %s\n", diag->diagnosticSetId);
  printf("Condition: %d\n", diag->condition);
  if (diag->addinfo)
    printf("Info: %s\n", diag->addinfo);
}
