#include "shared_course_request_xml.h"

char big_buffer[1000];
char global_file_path[MAX_PATH + 1];


static 
void critical_xml_parser_error(char *error, char *function_name, char *detail)
{
 char msg[MAX_PATH + 1];  /* some large string, not too concerned if truncated */
 
 snprintf(msg, MAX_PATH, "XML parser error while parsing<br />%s<br />in shared_course_request_xml.c : %s : %s", 
                        global_file_path, function_name, detail);
 *(msg + MAX_PATH) = '\0';

 cs_critical_error(error, msg);
}





static void startElement(void *userData, const char *name, const char **atts)
{
    REQUEST_COURSE_LIST *list = userData;

    if(strcmp(name, "request") == 0) 
    {
       if(!list->head)
       {
	  list->head = (REQUEST_COURSE *)malloc(sizeof(REQUEST_COURSE));
	  if(!list->head)
              critical_xml_parser_error(ERR_MALLOC_FAILED, "StartElement()", "allocating memory for list-&gt;head" );

	  list->current = list->head;
          list->head->next = 0;
       }
       else
       {
	   list->current->next=(REQUEST_COURSE *)malloc(sizeof(REQUEST_COURSE));
	   if(!list->current->next)
              critical_xml_parser_error(ERR_MALLOC_FAILED, "StartElement()", "allocating memory for list-&gt;current-&gt;next" );

	   list->current = list->current->next;
	   list->current->next = 0;
       }
    }
    
    memset(big_buffer, 0, strlen(big_buffer));
}







static void endElement(void *userData, const char *name)
{
    REQUEST_COURSE_LIST *list = userData;
    
    if(strcmp(name, "faculty_realname") == 0) 
    {
       strtrm(big_buffer);
       strncpy(list->current->realname, big_buffer, MAX_NAME + 1);
       *(list->current->realname + MAX_NAME) = '\0';
    }
    else if(strcmp(name, "faculty_username") == 0)
    {
       strtrm(big_buffer);
       strncpy(list->current->username, big_buffer, MAX_USERNAME + 1);
       *(list->current->username + MAX_USERNAME) = '\0';
    }
    else if(strcmp(name, "sis_id") == 0)
    {
       strtrm(big_buffer);
       strncpy(list->current->sis_id, big_buffer, MAX_COURSE_ID + 1);
       *(list->current->sis_id + MAX_COURSE_ID) = '\0';
    }
    else if(strcmp(name, "subdir") == 0)
    {
       strtrm(big_buffer);
       strncpy(list->current->subdir, big_buffer, MAX_COURSE_SUBDIR + 1);
       *(list->current->subdir + MAX_COURSE_SUBDIR) = '\0';
    }
    else if(strcmp(name, "new_id")==0)
    {
       strtrm(big_buffer);
       strncpy(list->current->new_id, big_buffer, MAX_COURSE_ID + 1);
       *(list->current->new_id + MAX_COURSE_ID) = '\0';
    }
    else if(strcmp(name, "course_code") ==0)
    {
       strtrm(big_buffer);
       strncpy(list->current->course_code, big_buffer, MAX_COURSE_NO + 1);
       *(list->current->course_code + MAX_COURSE_NO) = '\0';
    }
    else if(strcmp(name, "course_title") ==0)
    {
       strtrm(big_buffer);
       strncpy(list->current->course_title, big_buffer, MAX_COURSE_TITLE + 1);
       *(list->current->course_title + MAX_COURSE_TITLE) = '\0';
    }  
    else if(strcmp(name, "course_term") ==0)
    {
       strtrm(big_buffer);
       strncpy(list->current->course_semester, big_buffer, MAX_SEMESTER + 1);
       *(list->current->course_semester + MAX_SEMESTER) = '\0';
    }  
    else if(strcmp(name, "time") ==0)
    {
       strtrm(big_buffer);
       strncpy(list->current->timestring, big_buffer, MAX_PATH + 1);
       *(list->current->timestring + MAX_PATH) = '\0';
    }

    memset(big_buffer, 0, strlen(big_buffer));
}




static void startCharacter(void *userData, const char *text, int len)
{
	strncat(big_buffer, text, len);
}

void  free_request_head(REQUEST_COURSE *head)
{
      REQUEST_COURSE *ptr;
      while(head)
      {
             ptr = head->next;
             free(head);
             head = ptr;
      }

}




void free_request_list( REQUEST_COURSE_LIST *list)
{
  if(list) 
  {
    free_request_head(list->head);
    free(list);
  }
}



void *
xml_request_course_parser(char *file)
{
   char  *buf, *error_buf;
   REQUEST_COURSE_LIST *list;
   XML_Parser parser;
   FILE *fp;
   struct stat file_stat;


    /* copy the path to the global string, so it can be 
    ** used to report intelligent error messages 
    */ 
    strncpy(global_file_path, file, MAX_PATH + 1);
    *(global_file_path + MAX_PATH) = '\0';

    /*initialize list */
    list = (REQUEST_COURSE_LIST *)malloc(sizeof(REQUEST_COURSE_LIST));
    if(!list)
        critical_xml_parser_error(ERR_MALLOC_FAILED, "xml_request_course_parser()", "allocating memory for list" );

    list->head = 0;
    list->current = 0;

    if(stat(file, &file_stat))
	 cs_critical_error(ERR_FOPEN_READ_FAILED, "");
    buf = (char*)malloc(file_stat.st_size);
    if(!buf)
       critical_xml_parser_error(ERR_MALLOC_FAILED, "xml_request_course_parser()", "allocating memory to hold entire xml file" );

    fp = fopen(file, "r");
    if(!fp)
        cs_critical_error(ERR_FOPEN_READ_FAILED, file);
    get_shared_lock(fileno(fp), 1);
    if(fread(buf, file_stat.st_size, 1, fp) != 1)
	cs_critical_error(ERR_FREAD_FAILED, file);
    release_lock(fileno(fp));


    parser = XML_ParserCreate(NULL);
    XML_SetUserData(parser, list);
    XML_SetElementHandler(parser, startElement, endElement);
    XML_SetCharacterDataHandler(parser, startCharacter);
    if(!XML_Parse(parser, buf, file_stat.st_size, 1))
    {
      error_buf = malloc_str(XML_ErrorString(XML_GetErrorCode(parser)));
      critical_xml_parser_error(ERR_XML_PARSER, "xml request_course_parser()", error_buf? error_buf: "Parse failed");
    }

    XML_ParserFree(parser);
    return list;

}
      

void
get_request_list_filename( char *div, char *file)
{
    snprintf(file, MAX_PATH +1, "%s/%s", AUTO_UPDATE_REQUEST_PATH, div); 
}

