#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "../xmlparse.h"
#include "../global.h"
#include "shared_roster_xml_parser.h"
#include "shared_person_list.h"
#include "shared_survey_string.h"
#include "shared_strtrm.h"
#include "shared_cs_util.h"

#define MAX_BUFFER 1000
char big_buffer[MAX_BUFFER];
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_roster_xml_parser.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)
{
    XML_COURSE_INFO_LIST *list = userData;
    int i;

    if(strcmp(name, "course") == 0) 
    {
       if(!list->head)
       {
         list->head = (XML_COURSE_INFO*)malloc(sizeof(XML_COURSE_INFO));
         if(!list->head)
              critical_xml_parser_error(ERR_MALLOC_FAILED, "StartElement()", "allocating memory for list-&gt;head" );
	 for(i =0; atts[i]; i+=2)
         {
           if(strcmp(atts[i], "subdir")==0)
            {
             strncpy(list->head->subdir, atts[i+1], MAX_COURSE_SUBDIR +1);
             *(list->head->subdir + MAX_COURSE_SUBDIR) = '\0';
             strtrm(list->head->subdir);  /* shared_strtrm.c */
            }  
           if(strcmp(atts[i], "id")==0)
            {
              strncpy(list->head->dir_id, atts[i+1], MAX_COURSE_ID +1);
              *(list->head->dir_id + MAX_COURSE_ID) = '\0';
              strtrm(list->head->dir_id);    /* shared_strtrm.c */
            }  
        }
	  list->current = list->head;
	  list->current->instructor_title[0] = '\0';
	  list->current->real_dir_id[0] = '\0';
          list->current->user_head = 0;
          list->current->user_current = 0;
          list->head->next = 0;
       }
       else
       {
	   list->current->next=(XML_COURSE_INFO*)malloc(sizeof(XML_COURSE_INFO));
	   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->instructor_title[0] = '\0';
	   list->current->real_dir_id[0] = '\0';
           for(i =0; atts[i]; i+=2)
           {
             if(strcmp(atts[i], "subdir")==0)
              {
               strncpy(list->current->subdir, atts[i+1], MAX_COURSE_SUBDIR +1);
               *(list->current->subdir + MAX_COURSE_SUBDIR) = '\0';
               strtrm(list->current->subdir);  /* shared_strtrm.c */
              }  
             if(strcmp(atts[i], "id")==0)
              {
               strncpy(list->current->dir_id, atts[i+1], MAX_COURSE_ID +1);
               *(list->current->dir_id + MAX_COURSE_ID) = '\0';
               strtrm(list->current->dir_id);   /* shared_strtrm.c */
              }  
           }
	   list->current->next = 0;
           list->current->user_head = 0;
           list->current->user_current = 0;
       }
    }
    if(strcmp(name,"user") == 0)
    {
       if(!list->current->user_head)
       {
	   list->current->user_head = (P_NODE *)malloc(sizeof(P_NODE));
	   if(!list->current->user_head)
	       critical_xml_parser_error(ERR_MALLOC_FAILED, "startElement()", "allocating memory for list-&gt;current-&gt;user_head" );
	   strncpy(list->current->user_head->data.id, atts[1], MAX_ID +1);
	   *(list->current->user_head->data.id + MAX_ID) = '\0';
	   strtrm(list->current->user_head->data.id);  /* shared_strtrm.c */
	   list->current->user_current = list->current->user_head;
	   list->current->user_current->next =0;
       }
       else
       {
	   list->current->user_current->next = (P_NODE *)malloc(sizeof(P_NODE));
           if(!list->current->user_current->next)
	       critical_xml_parser_error(ERR_MALLOC_FAILED, "startElement()", "allocating memory for list-&gt;current-&gt;user_current-&gt;next" );           
	   list->current->user_current = list->current->user_current->next;
	   strncpy(list->current->user_current->data.id, atts[1], MAX_ID +1);
	   *(list->current->user_current->data.id + MAX_ID) = '\0';
	   strtrm(list->current->user_current->data.id);  /* shared_strtrm.c */
	   list->current->user_current->next =0;
       }
    }
    
    memset(big_buffer, 0, MAX_BUFFER);
}







static void endElement(void *userData, const char *name)
{
    XML_COURSE_INFO_LIST *list = userData;
    char *ptr;


    if(strcmp(name, "course_no") == 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->title, big_buffer, MAX_COURSE_TITLE + 1);
       *(list->current->title + MAX_COURSE_TITLE) = '\0';
    }
    else if(strcmp(name, "teacher_title") == 0)
    {
       strtrm(big_buffer);
       strncpy(list->current->instructor_title, big_buffer, MAX_INSTRUCTOR + 1);
       *(list->current->instructor_title + MAX_INSTRUCTOR) = '\0';
    }
    else if(strcmp(name, "term") == 0)
    {
       strtrm(big_buffer);
       ptr = 0;      /* so compiler won't complain if next #ifdef is skipped */
       
       /**** The next kludge adds one to the year if this is the spring semester
       ***** This is ONLY for Western New England College 
       ****/

#ifdef ADD_ONE_TO_SPRING_YEAR       
       char *nine;
       if(strstr(big_buffer,"Spring "))
        {
         ptr = strchr(big_buffer,'\0');
         if(ptr && (ptr > big_buffer))
	 {
            nine = ptr -1;
            if( *nine == '9')
	        *(nine -1) +=1;

            *(ptr - 1) += 1;
	 }
        }            
#endif

        
       strncpy(list->current->semester, big_buffer, MAX_SEMESTER + 1);
       *(list->current->semester + MAX_SEMESTER) = '\0';
    }
    else if(strcmp(name, "first")==0)
    {
       strtrm(big_buffer);
       strncpy(list->current->user_current->data.realname, big_buffer, MAX_NAME + 1);
       *(list->current->user_current->data.realname + MAX_NAME) = '\0';
    }
    else if(strcmp(name, "last") ==0)
    {
       strtrm(big_buffer);
       strncpy(list->current->user_current->data.lastname, big_buffer, MAX_NAME + 1);
       *(list->current->user_current->data.lastname + MAX_NAME) = '\0';
    }
    else if(strcmp(name, "username") ==0)
    {
       strtrm(big_buffer);
       if(strlen(big_buffer) == 0)
         list->current->user_current->data.username[0] = '\0';
       else
        {	  
          strncpy(list->current->user_current->data.username, big_buffer, MAX_USERNAME + 1);
          *(list->current->user_current->data.username + MAX_USERNAME) = '\0';
        }  
    }
    else if(strcmp(name, "group") ==0)
    {
       strtrm(big_buffer);
       if(strcmp(big_buffer, "faculty")==0)
         list->current->user_current->data.group = FACULTY;
       else
         list->current->user_current->data.group = STUDENT;
    }

    memset(big_buffer, 0, MAX_BUFFER);
}




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





void free_xml_data_list( XML_COURSE_INFO_LIST *list)
{
  XML_COURSE_INFO *ptr;
  list->current = list->head;
 
  while(list->current)
  {
     ptr = list->current->next;
     if(list->current->user_head)
	 free_option_person_list(list->current->user_head);
     free(list->current);
     list->current = ptr;
  }
  free(list);
}


/* 'buf' is a buffer containing the contents of the xml file
** that was  read from 'path'.
*/

void *
xml_course_data_parser(char *buf, const char *path)
{
   char  *error_buf;
   XML_COURSE_INFO_LIST *list;
   XML_Parser parser;
  
    /* copy the path to the global string, so it can be 
    ** used to report intelligent error messages 
    */ 
    strncpy(global_file_path, path, MAX_PATH + 1);
    *(global_file_path + MAX_PATH) = '\0';

    /*initialize list */
    list = (XML_COURSE_INFO_LIST *)malloc(sizeof(XML_COURSE_INFO_LIST));
    if(!list)
       critical_xml_parser_error(ERR_MALLOC_FAILED, "xml_course_data_parser()", "allocating memory for list");
    list->head = 0;
    list->current = 0;

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

}

      
void write_roster_xml_data(FILE *fp, XML_COURSE_INFO_LIST *list)
{
   char *str;
   P_NODE *ptr;

   fprintf(fp,"<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n");
   fprintf(fp, "<!-- Manhattan course data -->\n");
   fprintf(fp, "<courses>\n");
   for(list->current = list->head; list->current; list->current = list->current->next)
   {
      fprintf(fp, "   <course subdir=\"%s\" id=\"%s\">\n", list->current->subdir, list->current->dir_id);
      str = replace_sp(list->current->course_code);
      fprintf(fp, "      <course_no>%s</course_no>\n", str);
      free(str);

      str = replace_sp(list->current->title);
      fprintf(fp, "      <course_title>%s</course_title>\n", str);
      free(str);
      if(strlen(list->current->instructor_title))
      {
         str = replace_sp(list->current->instructor_title);
         fprintf(fp, "      <teacher_title>%s</teacher_title>\n", str);
	 free(str);
      }
      str = replace_sp(list->current->semester);
      fprintf(fp, "      <term>%s</term>\n", str);
      free(str);
      fprintf(fp, "      <users>\n");
      for( ptr = list->current->user_head; ptr; ptr = ptr->next)
      {
          fprintf(fp, "      <user id=\"%s\">\n", ptr->data.id);
	  str = replace_sp(ptr->data.realname);
          fprintf(fp, "        <first>%s</first>\n", str);
	  free(str);

	  str = replace_sp(ptr->data.lastname);
          fprintf(fp, "        <last>%s</last>\n", str);
	  free(str);
          fprintf(fp, "        <username></username>\n");
	  fprintf(fp, "        <group>%s</group>\n",ptr->data.group==FACULTY?"faculty":"student");
	  fprintf(fp, "      </user>\n");
      }
      fprintf(fp, "        </users>\n");
      fprintf(fp, "     </course>\n");
   }
   fprintf(fp, "</courses>\n");
}

