#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/unistd.h>
#include "../xmlparse.h"
#include "shared_util.h"
#include "shared_survey_string.h"
#include "shared_record_parser.h"
#include "shared_lock.h"
#include "shared_cs_util.h"

char big_buffer[500];

static RESULT *
find_same_id(RECORD *list, int id)
{
   RESULT  *ptr;
   ptr = list->head;
   while(ptr)
   {
       if(ptr->id == id)
		return ptr;
        ptr = ptr->next;
   }
   return 0;
}




static VALUE_COUNT * 
find_same_value(RESULT *list, const char *value)
{
    VALUE_COUNT *ptr;
    ptr = list->value_head;
    while(ptr)
    {
        if(strcmp(ptr->value, value)== 0)
	    return ptr;
	ptr = ptr->next;
    }
    return 0;
}
    


static void 
StartElement(void *userData, const char *name, const char **atts) 
{
    RECORD *list = userData;
    int i; 
    RESULT *ptr;
    VALUE_COUNT *val_ptr;

    if(strcmp(name, "result") == 0)
    {
	  i = 0;
         ptr = find_same_id(list, atoi(atts[i+1]));
	 if(!ptr)
	 {
	    if(!list->head)
	    {
		list->head = (RESULT*)malloc(sizeof(RESULT));
		list->current = list->head;
	    }
	    else
	    {
		list->current->next= (RESULT*)malloc(sizeof(RESULT));
		list->current = list->current->next;
	    }
            list->current->next = 0;
	    list->current->value_head = (VALUE_COUNT*)malloc(sizeof(VALUE_COUNT));
	    list->current->value_current = list->current->value_head;
	    list->current->value_current->next = 0;
	    list->current->id = atoi(atts[i+1]);
	    list->current->count = 1;
	    i = i+2;
	    list->current->value_current->value = malloc_str(atts[i+1]);
	    list->current->value_current->count = 1;
	    
	 }
	 else
	 {
	   ptr->count++;
	   i = i +2;
	   val_ptr = find_same_value(ptr, atts[i+1]);
	   if(!val_ptr)
	   {
	      ptr->value_current->next = (VALUE_COUNT*)malloc(sizeof(VALUE_COUNT));
	      ptr->value_current = ptr->value_current->next;
	      ptr->value_current->next = 0;
	      ptr->value_current->value = malloc_str(atts[i+1]);
	      ptr->value_current->count = 1;
	   }
	   else
	   {
	     val_ptr->count++;
	   }
	 }
    }
   memset(big_buffer, 0, strlen(big_buffer));
}


static void
EndElement(void *userData, const char *name)
{
    RECORD *list = userData;
  
  if(strcmp(name, "expect_takers") ==0)
     list->expect_takers = atoi(big_buffer);   
   memset(big_buffer, 0, strlen(big_buffer));
}




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




void
free_record_list(RECORD *list)
{
    RESULT  *ptr;
    VALUE_COUNT  *value_ptr;

    list->current = list->head;

    while(list->current)
    {
       
        ptr = list->current;
	
	if(ptr->value_head)
	{
	   ptr->value_current = ptr->value_head;
	   while(ptr->value_current)
	   {
	       value_ptr = ptr->value_current;
	       if(value_ptr->value)
		       free(value_ptr->value);
	       ptr->value_current = ptr->value_current->next;
	       free(value_ptr);
	   }
	}
	list->current = list->current->next;
	free(ptr);
    }
   if(list)
      free(list);
}
    

	
void *
record_parser(char *filename)
{
    char *buf, *error_buf;
    RECORD *list;
    FILE *fp;
    struct stat file_stat;
    XML_Parser parser;
    
    /*initialize list */
    list = (RECORD *)malloc(sizeof(RECORD));
    list->head = 0;
    list->current = 0;
    list->expect_takers =0; 

    if(stat(filename, &file_stat))
       cs_critical_error( ERR_FOPEN_READ_FAILED, filename);
    buf = (char*)malloc(file_stat.st_size);
    if(!buf)
	cs_critical_error(ERR_MALLOC_FAILED, "");
    
    fp = fopen(filename, "r");
    if(!fp)
	cs_critical_error( ERR_FOPEN_READ_FAILED, filename);
    get_shared_lock(fileno(fp), 1);
    if(fread(buf, file_stat.st_size, 1, fp) != 1)
	cs_critical_error( ERR_FREAD_FAILED, filename);
    release_lock(fileno(fp));
    fclose(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)));
     
     cs_critical_error(ERR_XML_PARSER, error_buf);
     free(error_buf);
     }
    XML_ParserFree(parser);
    free(buf);
    return list;
    
}
     

