#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 "../survey.h"

#include "shared_survey_util.h"
#include "shared_survey_string.h"
#include "shared_lock.h"
#include "shared_cs_util.h"

char *buffer_big;
int max_buffer_big = 1000;

static void startElement(void *userData, const char *name, const char **atts)
{
    SURVEY_LIST *list = userData;
    char *tag = malloc_str(name);
    int i;

    /* is_likert_tag is in shared_survey_util.c */
    if(strcmp(tag, "title") == 0 || is_likert_tag(tag) ||
       strcmp(tag, "choice") ==0 || strcmp(tag, "text") ==0 ||
       strcmp(tag, "memo") == 0 || strcmp(tag, "custom") == 0)
    {
       if(!list->head)
       {
	  list->head = (SURVEY_DATA*)malloc(sizeof(SURVEY_DATA));
	  list->current = list->head;
          list->current->head = 0;
          list->current->steps_bgcolor = 0;
          list->current->current = 0;
          list->head->next = 0;
       }
       else
       {
	   list->current->next=(SURVEY_DATA*)malloc(sizeof(SURVEY_DATA));
	   list->current = list->current->next;
	   list->current->next = 0;
           list->current->head = 0;
          list->current->steps_bgcolor = 0;
           list->current->current = 0;
       }
    }
    if(strcmp(tag, "title") == 0)
    {
       list->current->tag_name = malloc_str(tag);
       for(i = 0; atts[i]; i = i+2)
       {
	  if(strcmp(atts[i], "id") == 0)
            list->current->id = atoi(atts[i +1]);
          else if(strcmp(atts[i], "bgcolor") == 0)
	    list->current->steps_bgcolor = malloc_str(atts[i +1]);
	  else
	    list->current->left_cols = malloc_str(atts[i +1]);

       }
       list->current->caption = 0;
       list->current->right_rows = 0;
    }
    else if(is_likert_tag(tag))    /* shared_survey_util.c */
    {
      list->current->tag_name = malloc_str(tag);
      for(i = 0; atts[i]; i = i+2)
      {
	if(strcmp(atts[i], "id") == 0)
	   list->current->id = atoi(atts[i+1]);
	else if(strcmp(atts[i], "steps") == 0)
           list->current->steps_bgcolor = malloc_str(atts[i +1]);
        else if(strcmp(atts[i], "lefttag") == 0)
           list->current->left_cols = malloc_str(atts[i +1]);
	else if(strcmp(atts[i], "righttag") ==0)
	   list->current->right_rows = malloc_str(atts[i +1]);
      }
      list->current->caption = 0;
    }
    else if(strcmp(tag, "memo") == 0)
    {
      list->current->tag_name = malloc_str(tag);
      for(i = 0; atts[i]; i = i+2)
      {
	if(strcmp(atts[i], "id") == 0)
	   list->current->id = atoi(atts[i+1]);
        else if(strcmp(atts[i], "cols") == 0)
           list->current->left_cols = malloc_str(atts[i +1]);
	else if(strcmp(atts[i], "rows") ==0)
	   list->current->right_rows = malloc_str(atts[i +1]);
      }
      list->current->caption = 0;
      list->current->steps_bgcolor = 0;
    }
    else if(strcmp(tag, "text") == 0 
            || strcmp(tag, "custom") ==0 )
    {
      list->current->tag_name = malloc_str(tag);
      for(i = 0; atts[i]; i = i+2)
      {
	if(strcmp(atts[i], "id") == 0)
	   list->current->id = atoi(atts[i+1]);
      }
      list->current->caption = 0;
      list->current->steps_bgcolor = 0;
      list->current->left_cols = 0;
      list->current->right_rows = 0;
    }
    else if(strcmp(tag, "choice") == 0)
    {
      list->current->tag_name = malloc_str(tag);
      for(i = 0; atts[i]; i = i+2)
      {
	if(strcmp(atts[i], "id") == 0)
	   list->current->id = atoi(atts[i+1]);
	if(strcmp(atts[i], "multi") ==0)
	   list->current->steps_bgcolor = malloc_str(atts[i +1]);
      }
      if(!list->current->steps_bgcolor)
	   list->current->steps_bgcolor = malloc_str("no");
      list->current->caption = 0;
      list->current->left_cols = 0;
      list->current->right_rows = 0;
    }
      
    else if(strcmp(tag, "element_choice")==0)
    {
      if(!list->current->head)
      {
	list->current->head = (ELE_CHOICE*)malloc(sizeof(ELE_CHOICE));
	list->current->current = list->current->head;
	list->current->current->next = 0;
      }
      else
      {
	list->current->current->next = (ELE_CHOICE*)malloc(sizeof(ELE_CHOICE));
        list->current->current = list->current->current->next;
	list->current->current->next = 0;
      }
    }
    free(tag);
    
    memset(buffer_big, 0, max_buffer_big);
}




static void endElement(void *userData, const char *name)
{
    SURVEY_LIST *list = userData;
    char *tag = malloc_str(name);
    if(strcmp(tag, "title") == 0 || is_likert_tag(tag) ||
       strcmp(tag, "choice") ==0 || strcmp(tag, "text") ==0 ||
       strcmp(tag, "memo") == 0 || strcmp(tag, "custom") == 0)
    {
       strtrim(buffer_big);
       list->current->caption = malloc_str(buffer_big);
    }
    else if(strcmp(tag, "element_choice") == 0)
    {
       strtrim(buffer_big);
       list->current->current->choice = malloc_str(buffer_big);
    }
    memset(buffer_big, 0, max_buffer_big);
    free(tag);
}





static void startCharacter(void *userData, const char *text, int len)
{

	if( (int)(strlen(text) + strlen(buffer_big)) >= max_buffer_big)
        {
              max_buffer_big = max_buffer_big * 2;
              buffer_big = realloc(buffer_big, sizeof(char)*(max_buffer_big));
	      
	}
	strncat(buffer_big, text, len);
}





void free_survey_data_list(SURVEY_LIST *list)
{
  SURVEY_DATA *ptr;
  ELE_CHOICE *ele_ptr;
  list->current = list->head;
 
  while(list->current)
  {
     ptr = list->current;
     if(ptr->tag_name)
       free(ptr->tag_name);
     if(ptr->steps_bgcolor)
       free(ptr->steps_bgcolor);
     if(ptr->caption)
       free(ptr->caption);
     if(ptr->left_cols)
       free(ptr->left_cols);
     if(ptr->right_rows)
       free(ptr->right_rows);
     if(list->current->head)
     {
	list->current->current = list->current->head;
        while(list->current->current)
	{
	   ele_ptr = list->current->current;
	   if(ele_ptr->choice)
	      free(ele_ptr->choice);
           list->current->current = list->current->current->next;
	   free(ele_ptr);
         }
     }
     list->current = list->current->next;
     free(ptr);
  }
  free(list);
}



void *
survey_data_parser(char *filename)
{
   char *buf, *error_buf;
   SURVEY_LIST *list;    /* survey.h */
   FILE *fp;
   struct stat file_stat;
   XML_Parser parser;

    /* buffer_big and max_buffer_big are globals at the top of this file */
    buffer_big = (char *)malloc(sizeof(char)*(max_buffer_big));   
    
    /*initialize list */
    list = (SURVEY_LIST *)malloc(sizeof(SURVEY_LIST));
    list->head = 0;
    list->current = 0;

    if(stat(filename, &file_stat))
       cs_critical_error( ERR_STAT_FAILED, filename);
       
       
    buf = (char*)malloc(file_stat.st_size);
    if(!buf)
      cs_critical_error( ERR_MALLOC_FAILED, "survey_data_parser()");

    fp = fopen(filename, "r");
    if(!fp)
      cs_critical_error( ERR_FOPEN_READ_FAILED, filename);
      
    get_shared_lock(fileno(fp), 1);   /* shared_lock.h */
    
    if(fread(buf, file_stat.st_size, 1, fp) != 1)
       cs_critical_error(ERR_FREAD_FAILED, filename);
       
    release_lock(fileno(fp));   /* shared_lock.c */
    
    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);
    free(buffer_big);
    return list;

}

      



