#include "shared_survey_modify.h"
#include "../global.h"
#include "shared_survey_xml_parser.h"
#include "shared_survey_string.h"
#include "shared_survey_util.h"
#include "shared_file_util.h"
#include "shared_survey_log.h"
#include "shared_survey_path_util.h"
#include "shared_util.h"
#include "shared_cs_util.h"

void
xml_header(FILE *fp)
{
  fprintf(fp, "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?>\n");
  fprintf(fp, "<survey>\n");
}





void
xml_close(FILE *fp)
{
     fprintf(fp, "%s", SURVEY_END_TAG);
}





void
write_title(FILE *fp, SURVEY_DATA *data)
{
  fprintf(fp, "   <%s id=\"%d\" bgcolor=\"%s\" link=\"%s\">\n",
         data->tag_name, data->id, data->steps_bgcolor, data->left_cols);
  fprintf(fp, "%s%s", SURVEY_CDATA_START, data->caption);
  fprintf(fp, "%s</%s>\n", SURVEY_CDATA_END, data->tag_name);
}





void
write_memo(FILE *fp, SURVEY_DATA *data )
{
  fprintf(fp, "   <%s id=\"%d\"  cols=\"%s\" rows=\"%s\" >\n",
	  data->tag_name, data->id,  data->left_cols, data->right_rows);
  fprintf(fp, "%s%s\n", SURVEY_CDATA_START, data->caption);
  fprintf(fp, "%s</%s>\n", SURVEY_CDATA_END, data->tag_name);
}





void
write_likert(FILE *fp, SURVEY_DATA *data)
{
  fprintf(fp, "   <%s id=\"%d\" steps=\"%s\" lefttag=\"%s\" righttag=\"%s\" >\n",
     data->tag_name, data->id, data->steps_bgcolor, data->left_cols, data->right_rows);
   fprintf(fp, "%s%s\n", SURVEY_CDATA_START,data->caption);
   fprintf(fp, "%s</%s>\n", SURVEY_CDATA_END, data->tag_name);
}





void
write_choice(FILE *fp, SURVEY_DATA *data)
{
   ELE_CHOICE *ptr;
   fprintf(fp, "   <%s id=\"%d\" multi=\"%s\">\n",
        data->tag_name, data->id , data->steps_bgcolor ? data->steps_bgcolor: "no");
  if(data->head)
  {
    for(ptr = data->head; ptr; ptr = ptr->next)
     fprintf(fp, "     <%s>%s%s%s</%s>\n", "element_choice", SURVEY_CDATA_START, ptr->choice, SURVEY_CDATA_END, "element_choice");   
  }
  fprintf(fp, "%s%s", SURVEY_CDATA_START,data->caption);
  fprintf(fp, "%s</%s>\n", SURVEY_CDATA_END,data->tag_name);
}






void
write_text_custom(FILE *fp, SURVEY_DATA *data)
{
   fprintf(fp, "   <%s id=\"%d\">\n", data->tag_name, data->id);
   fprintf(fp, "%s%s", SURVEY_CDATA_START, data->caption);
   fprintf(fp, "%s</%s>\n", SURVEY_CDATA_END, data->tag_name);
}







int get_id_count(const char *file_name)
{
 #define MAX_ID_COUNT 11
   FILE *fp;
   char line[MAX_ID_COUNT +1];
   fp = fopen(file_name, "r");
   if(!fp)
    cs_critical_error(ERR_FOPEN_READ_FAILED, "");
   if(!fgets(line, MAX_ID_COUNT+1, fp))
    cs_critical_error(ERR_FREAD_FAILED, "");
   fclose(fp);
    strtrim(line);
   return atoi(line) -1;
 #undef MAX_ID_COUNT
}



static 
void replace_sp_inleftright(SURVEY_DATA *data)
{
   char *str;

   if((data->left_cols && is_likert_tag(data->tag_name)))
   {
           str = replace_sp(data->left_cols);
	   if(str)
	   {
	      free(data->left_cols);
	      data->left_cols = malloc_str(str);
	      free(str);
	      str = 0;
	   }
   }
  if(data->right_rows && is_likert_tag(data->tag_name))
  {
           str = replace_sp(data->right_rows);
	   if(str)
	   {
	      free(data->right_rows);
	      data->right_rows = malloc_str(str);
	      free(str);
	      str = 0;
	   }
   }
    
}

static void
replace_sp_inlist(SURVEY_DATA *head)
{
 SURVEY_DATA *current;
 
     for (current = head; current; current=current->next)
     {
         if(is_likert_tag(current->tag_name))
              replace_sp_inleftright(current);
     }
} 









void write_one_tag(FILE *fp, SURVEY_DATA *written_data)
{

        if(strcmp(written_data->tag_name, "title")==0)
         {
	  write_title(fp, written_data);
	 } 
        else if(is_likert_tag(written_data->tag_name))   /* shared_survey_util.c */
	  write_likert(fp, written_data);
        else if(strcmp(written_data->tag_name, "choice") ==0)
         {
	  write_choice(fp, written_data);
        }
        else if(strcmp(written_data->tag_name, "memo") ==0)
	  write_memo(fp, written_data);
        else
	  write_text_custom(fp, written_data);
}



void
rewrite_xml_file(char *xml_file, SURVEY_DATA *new_data)
{
   SURVEY_LIST *list;
   SURVEY_DATA *written_data;
   FILE *fp;

   list = survey_data_parser(xml_file);
   if(!list->head)
       cs_critical_error(ERR_SURVEY_ERROR_1, "");
        //"Error 1 in rewrite_xml_file() - please contact server administrators to tell them about this problem!","");
   if(list->head)
   {
     write_to_log(xml_file);
     
     replace_sp_inlist(list->head);
     if(!list->head)
          cs_critical_error(ERR_SURVEY_ERROR_2, "");
        //"Error 2 in rewrite_xml_file() - please contact server administrators to tell them about this problem!","");
     else
     {
       fp = fopen(xml_file, "w");

       if(!fp)
         cs_critical_error(ERR_FOPEN_WRITE_FAILED, "");
       get_exclusive_lock(fileno(fp), 1);
      
      xml_header(fp);
      list->current = list->head;
       while(list->current)
       {
          if(list->current->id == new_data->id)
	     written_data = new_data;
          else
	     written_data = list->current;
          write_one_tag(fp, written_data);
	  list->current = list->current->next;
        }
        xml_close(fp);
       release_lock(fileno(fp));
       fclose(fp);
     }
   }
   free_survey_data_list(list);
}   





void
modify_action( SESSION *user, const char *count, SURVEY_DATA *data)
{
  char survey_path[MAX_PATH +1];
  char survey_file_path[MAX_PATH +1];

   get_survey_path(user, survey_path, count); /* shared_survey_path_util.c */
   snprintf(survey_file_path, MAX_PATH+1, "%s/%s",
        survey_path, SURVEY_XML_FNAME);
   rewrite_xml_file(survey_file_path, data);

}




void
insert_data(char *xml_file, SURVEY_DATA *new_data, int pre_id)
{
   SURVEY_LIST *list;
   FILE *fp;
   list = survey_data_parser(xml_file);
   if(!list->head)
     cs_critical_error(ERR_SURVEY_ERROR_1, "");
      //"Error 1 in insert_data() - please contact server administrators to tell them about this problem!","");
      
   if(list->head)
   {
     write_to_log(xml_file);
     replace_sp_inlist(list->head);
     if(!list->head)
            cs_critical_error(ERR_SURVEY_ERROR_2, "");
       //"Error 2 in insert_data() - please contact server administrators to tell them about this problem!","");
     else
     {
       fp = fopen(xml_file, "w");
       if(!fp)
       cs_critical_error(ERR_FOPEN_WRITE_FAILED, "");

        get_exclusive_lock(fileno(fp), 1);

        xml_header(fp);
       for(list->current = list->head; list->current; list->current = list->current->next)
       {
      
        if(list->current->id == pre_id)
	{
             write_one_tag(fp, list->current);
	     write_one_tag(fp, new_data);
	}
        else
          write_one_tag(fp, list->current);
       }
       xml_close(fp);
       release_lock(fileno(fp));
       fclose(fp);
    }
   }
   free_survey_data_list(list);
}   
   




void
insert_action( SESSION *user, const char *count, 
		SURVEY_DATA *data, int pre_id)
{
  char survey_path[MAX_PATH +1];
  char survey_file_path[MAX_PATH +1];
     
   get_survey_path(user, survey_path, count);    /*shared_survey_path_util.c */
   snprintf(survey_file_path, MAX_PATH+1, "%s/%s",
        survey_path, SURVEY_XML_FNAME);
   insert_data(survey_file_path, data,  pre_id);

}






void
paste_action( SESSION *user, int crs, const char *key, 
		const char *count, int pre_id)
{
   char file_path[MAX_PATH +1];
   char survey_path[MAX_PATH +1];
   SURVEY_LIST *list;
   SURVEY_DATA *data;

   get_survey_path(user, survey_path, count);  /*shared_survey_path_util.c */

   snprintf(file_path, MAX_PATH +1, "%s/%s",survey_path, SURVEY_CLIPBOARD_FNAME);
   if(!file_exists(file_path))
     printf("Location: %s?crs=%d&id=%s&count=%s&pre_id=%d#%d\n\n",
        "survey_new", crs, key, count, pre_id, pre_id);
   else
   {
       list = survey_data_parser(file_path);
       replace_sp_inlist(list->head);
       data = get_clipboard_data(list);
       snprintf(file_path, MAX_PATH +1, "%s/%s",survey_path, SURVEY_XML_FNAME);
       data->id = get_valid_tag_id(file_path);
       insert_action( user, count, data, pre_id);
       free_survey_data(data);
       free_survey_data_list(list);
    }
}




int 
find_previous_one(SURVEY_LIST *list, int delete_id)
{
    SURVEY_DATA *data =0;

    if(list && list->head)
    {
        for(list->current = list->head; list->current; list->current = list->current->next)
	{
	    if(list->current->id == delete_id)
		    break;
	    data = list->current;
	}
    }
    if(data)
	return data->id;
    return 0;
}







void
delete_data(char *xml_file, int delete_id, int *before_me)
{
   FILE *fp;
   SURVEY_LIST *list =0;


   list = survey_data_parser(xml_file);
   if(!list->head)
     cs_critical_error(ERR_SURVEY_ERROR_1, "");
       // cs_critical_error("Error 1 in delete_data() - please contact server administrators to tell them about this problem!","");
   if(list->head)
   {
    *before_me = find_previous_one(list, delete_id);
     write_to_log(xml_file);

     replace_sp_inlist(list->head);
     if(!list->head)
        cs_critical_error(ERR_SURVEY_ERROR_2, "");
         //cs_critical_error("Error 2 in delete_data() - please contact server administrators to tell them about this problem!","");
     else
     {
       fp = fopen(xml_file, "w");
       if(!fp)
         cs_critical_error(ERR_FOPEN_WRITE_FAILED, "");
       get_exclusive_lock(fileno(fp), 1);
       xml_header(fp);
       
       list->current = list->head;
       while(list->current)
       {
        if(list->current->id != delete_id)
             write_one_tag(fp, list->current);
	list->current = list->current->next;
	
        }
        xml_close(fp);
       release_lock(fileno(fp));
       fclose(fp);
     }
  }
  free_survey_data_list(list);

}   






void
delete_action( SESSION *user, const char* count, int delete_id, int *before_me)
{
  char survey_path[MAX_PATH +1];
  char survey_file_path[MAX_PATH +1];
  
  get_survey_path(user, survey_path, count);  /*shared_survey_path_util.c */
  snprintf(survey_file_path, MAX_PATH+1, "%s/%s",survey_path, SURVEY_XML_FNAME);
  
  delete_data(survey_file_path, delete_id, before_me);
}

   




void
write_to_clipboard(const char *count, SURVEY_DATA *data, SESSION *user)
{
    char file_path[MAX_PATH +1];
    char survey_path[MAX_PATH +1];
    FILE *fp;
    
   
    get_survey_path(user, survey_path, count);
    snprintf(file_path, MAX_PATH+1, "%s/%s",survey_path, SURVEY_CLIPBOARD_FNAME);

    fp = fopen(file_path, "w");
    if(!fp)
       cs_critical_error(ERR_FOPEN_WRITE_FAILED, "");
     
     get_exclusive_lock(fileno(fp), 1);
     xml_header(fp);
     write_one_tag(fp, data);
    xml_close(fp);
    release_lock(fileno(fp));
    fclose(fp);
}






int
get_tag_id()
{
   int seed, i;
   seed = time(NULL);
   srand(seed);
   i = 100000+(int)(900000.0 *rand()/(RAND_MAX + 1000000.0));

   return i;
}






static int 
used_id(int id, SURVEY_LIST *list)
{
    if(list && list->head)
    {
        for(list->current = list->head; list->current; list->current = list->current->next)
		if(list->current->id == id)
		   return 1;
    }
    return 0;
}






int
get_valid_tag_id( char *file)
{
   SURVEY_LIST *list;
   int i = 0;

   list = survey_data_parser(file);
   do
   {
     i = get_tag_id();
   }while(used_id(i, list));
   free_survey_data_list(list);
   return i;
}







void
delete_cut_action(SURVEY_LIST *list,  SESSION *user, const char *count, int delete_id, int *before_me)
{
   FILE *fp;
   char survey_path[MAX_PATH +1];
   char xml_file[MAX_PATH +1];
  
   get_survey_path(user, survey_path, count);  /*shared_survey_path_util.c */
   snprintf(xml_file, MAX_PATH+1, "%s/%s",survey_path, SURVEY_XML_FNAME);

   if(!list->head)
        cs_critical_error(ERR_SURVEY_ERROR_1, "");
      //"Error 1 in delete_data() - please contact server administrators to tell them about this problem!","");
        //cs_critical_error("Error 1 in delete_data() - please contact server administrators to tell them about this problem!","");
   if(list->head)
   {
    *before_me = find_previous_one(list, delete_id);
     write_to_log(xml_file);

     replace_sp_inlist(list->head);
     if(!list->head)
        cs_critical_error(ERR_SURVEY_ERROR_2, "");
         //cs_critical_error("Error 2 in delete_data() - please contact server administrators to tell them about this problem!","");
     else
     {
       fp = fopen(xml_file, "w");
       if(!fp)
         cs_critical_error(ERR_FOPEN_WRITE_FAILED, "");
       get_exclusive_lock(fileno(fp), 1);
       xml_header(fp);
       
       list->current = list->head;
       while(list->current)
       {
        if(list->current->id != delete_id)
             write_one_tag(fp, list->current);
	list->current = list->current->next;
	
        }
        xml_close(fp);
       release_lock(fileno(fp));
       fclose(fp);
     }
  }
}





void
delete_action_cut(SURVEY_LIST *list,  const char *xml_file, int delete_id, int *before_me)
{
   FILE *fp;

   if(!list->head)
        cs_critical_error(ERR_SURVEY_ERROR_1, "");
        //cs_critical_error("Error 1 in delete_data() - please contact server administrators to tell them about this problem!","");
   if(list->head)
   {
    *before_me = find_previous_one(list, delete_id);
     write_to_log(xml_file);

     replace_sp_inlist(list->head);
     if(!list->head)
        cs_critical_error(ERR_SURVEY_ERROR_2, "");
         //cs_critical_error("Error 2 in delete_data() - please contact server administrators to tell them about this problem!","");
     else
     {
       fp = fopen(xml_file, "w");
       if(!fp)
         cs_critical_error(ERR_FOPEN_WRITE_FAILED, "");
       get_exclusive_lock(fileno(fp), 1);
       xml_header(fp);
       
       list->current = list->head;
       while(list->current)
       {
        if(list->current->id != delete_id)
             write_one_tag(fp, list->current);
	list->current = list->current->next;
	
        }
        xml_close(fp);
       release_lock(fileno(fp));
       fclose(fp);
     }
  }
}
