/* Implementation of citation routines. */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "util.h"
#include "techrep.h"
#include "citation.h"

#define END_OF_FILE     0
#define END_OF_CITATION 1
#define ENTRY_OK        2
#define ENTRY_BAD       3

/* creation, deletion, and access routines for Citations */
CitationPtr
initCitation()
{
   CitationPtr C;

   C = (CitationPtr) malloc (sizeof(Citation));
   if (C == NULL) {
      return (C);
   }
   C->author = NULL;
   C->trId = NULL;
   C->poster = NULL;
   C->title  = NULL;
   C->date = NULL;
   C->modified = NULL;
   C->keywords = NULL;
   C->categories = NULL;
   C->abstract = NULL;
   C->url = NULL;
   C->org = NULL;
   C->filepath = NULL;
   return (C);
}

void
freeCitation (CitationPtr C)
{
   if (C->author) {
      free ((void *) C->author );
   }
   if (C->trId) {
      free ((void *) C->trId );
   }
   if (C->poster) {
      free ((void *) C->poster );
   }
   if (C->title) {
      free ((void *) C->title );
   }
   if (C->date) {
      free ((void *) C->date );
   }
   if (C->keywords) {
      free ((void *) C->keywords );
   }
   if (C->categories) {
      free ((void *) C->categories );
   }
   if (C->abstract) {
      free ((void *) C->abstract );
   }
   if (C->url) {
      free ((void *) C->url );
   }
   if (C->org) {
      free ((void *) C->org );
   }
   if (C->modified) {
      free ((void *) C->modified );
   }
   if (C->filepath) {
      free ((void *) C->filepath );
   }
   free ((void *) C);
}

char *
getAuthor (CitationPtr C)
{
   return (C->author);
}
char *
getTrId (CitationPtr C)
{
   return (C->trId);
}
char *
getPoster (CitationPtr C)
{
   return (C->poster);
}
char *
getTitle (CitationPtr C)
{
   return (C->title);
}
char *
getDate (CitationPtr C)
{
   return (C->date);
}
char *
getKeywords (CitationPtr C)
{
   return (C->keywords);
}
char *
getCategories (CitationPtr C)
{
   return (C->categories);
}
char *
getAbstract (CitationPtr C)
{
   return (C->abstract);
}
char *
getModDate (CitationPtr C)
{
   return (C->modified);
}
char *
getUrl (CitationPtr C)
{
   return (C->url);
}
char *
getOrg (CitationPtr C)
{
   return (C->org);
}
char *
getFilepath (CitationPtr C)
{
   return (C->filepath);
}

/* read a single citation from the citation file */
CitationPtr
read_one_citation (FILE *fp)
{
   char line[STRING_SIZE];
   int  retval;
   char *s;
   CitationPtr C;
   char author[STRING_SIZE];
   char *buffer;
   int ch;

   C = initCitation();
   if (!C) {
      return (NULL);
   }

   buffer = (char *) malloc(ABS_SIZE);
   if (!buffer) {
      return (NULL);
   }

   author[0] = '\0';
   do {
      retval = readEntry(fp, buffer);

      if (strlen(buffer) == 0)
         break;

      buffer[strlen(buffer)-1]='\0';

      switch (buffer[1]){
        case REF_AUTHOR: /* author, perhaps multiple lines of authors */
          if (strcmp(author,"")!=0) 
             strcat(author,";");
          strcat(author, buffer+3);
          break;
        case REF_REPORT:  /* tr number */
          C->trId = strdup(buffer+3);
          break;
        case REF_TITLE:  /* title */
          C->title = strdup(buffer+3);
          break;
        case REF_DATE:  /* date */
          C->date = strdup(buffer+3);
          break;
        case REF_KEYWORDS:  /* keywords */
          C->keywords = strdup(buffer+3);
          break;
        case REF_CATEGORY:  /* categories */
          C->categories = strdup(buffer+3);
          break;
        case REF_LASTMOD:  /* last modified date */
          C->modified = strdup(buffer+3);
          break;
        case REF_URL:  /* url */
          C->url = strdup(buffer+3);
          break;
        case REF_INST:  /* organization */
          C->org = strdup(buffer+3);
          break;
        case REF_ABSTRACT:  /* abstract */
          C->abstract = strdup(buffer+3);
          break;
        default:
          break;
      }  /* switch */

   } while ((retval != END_OF_CITATION) && (retval != END_OF_FILE));

   /* eat blank lines */
   while (((ch = getc(fp)) != '%') && (ch != EOF)) ;
   ungetc (ch, fp);  /* return the '%' */

   if (strcmp (author, "")) {
      C->author = strdup (author);
   }

   if (buffer) 
      free (buffer);

   /* Might miss the last citation if there is no blank line */
   if (retval == END_OF_FILE) {
      freeCitation(C);
      return (NULL);
   } else {
      return (C);
   }

} /* read_one_citation */

int
write_one_citation (FILE *fp, CitationPtr C)
{
   char *s1, *s2;
   if (C->url) 
      fprintf (fp, "%%%c %s\n", REF_URL, C->url);
   if (C->author) {
      s1 = C->author;
      while (s2 = strchr(s1, ';')) {
         *s2 = '\0';
         fprintf (fp, "%%%c %s\n", REF_AUTHOR, s1);
         s1 = s2+1;
      }
      fprintf (fp, "%%%c %s\n", REF_AUTHOR, s1);
   }
   if (C->title) 
      fprintf (fp, "%%%c %s\n", REF_TITLE, C->title);
   if (C->trId) 
      fprintf (fp, "%%%c %s\n", REF_REPORT, C->trId);
   if (C->date) 
      fprintf (fp, "%%%c %s\n", REF_DATE, C->date);
   if (C->org) 
      fprintf (fp, "%%%c %s\n", REF_INST, C->org);
   if (C->keywords) 
      fprintf (fp, "%%%c %s\n", REF_KEYWORDS, C->keywords);
   if (C->categories) 
      fprintf (fp, "%%%c %s\n", REF_CATEGORY, C->categories);
   if (C->abstract) 
      fprintf (fp, "%%%c %s\n", REF_ABSTRACT, C->abstract);
   if (C->modified) 
      fprintf (fp, "%%%c %s\n", REF_LASTMOD, C->modified);
   fprintf (fp, "\n");
   return 0;
}

int  
readEntry (FILE *fp, char *buffer)
{
   char  line[STRING_SIZE];
   char *s;
   void *retval;
   int   ch;

   buffer[0] = '\0';
   do {
      retval = fgets(line, STRING_SIZE, fp);
      if (!retval) {
         if (strlen(buffer)) {
            return END_OF_CITATION;	
         } else {
            return END_OF_FILE;
         }
      }
      s = stripLeadingBlanks(line);
      if (strlen(s) == 0) {
         return END_OF_CITATION;
      }
      strcat (buffer, line);

      ch = getc(fp);
      ungetc (ch, fp);
      if (ch == '%') {
         return ENTRY_OK;
      }
   } while (1);
}

