#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>

#include "global.h"
#include "survey.h"

#include "manhat-lib/shared_survey_update_info.h"
#include "manhat-lib/shared_survey_util.h"
#include "manhat-lib/shared_survey_string.h"
#include "manhat-lib/shared_survey_info_list_parser.h"
#include "manhat-lib/shared_person_list.h"
#include "manhat-lib/shared_super_key.h"
#include "manhat-lib/shared_survey_deliver_list.h"
#include "manhat-lib/shared_super_list.h"
#include "manhat-lib/shared_strtrm.h"
#include "manhat-lib/shared_lock.h"
#include "manhat-lib/shared_survey_path_util.h"
#include "manhat-lib/shared_super_util.h"

#include "manhat-lib/shared_cs_util.h"

typedef struct survey_user_course
{
    char username[MAX_USERNAME +1];
    GROUP_TYPE group; 
    COURSE_LIST_NODE *course_node_head;
    COURSE_LIST_NODE *course_node_current;
    struct survey_user_course *next;

}SURVEY_USER_COURSE;

typedef struct survey_user_course_list
{
    SURVEY_USER_COURSE *head;
    SURVEY_USER_COURSE *current;

}SURVEY_USER_COURSE_LIST;


SURVEY_USER_COURSE *
get_one_user_course(SURVEY_USER_COURSE_LIST *u_head, P_NODE *one_node)
{
    SURVEY_USER_COURSE *user_ptr; 
      
    for(user_ptr = u_head->head; user_ptr; user_ptr = user_ptr->next)
    {
       if(!strcmp(user_ptr->username, one_node->data.username))
	   return user_ptr;
    }
    return 0;
}
    
SURVEY_USER_COURSE_LIST *
build_survey_user_course_list(SURVEY_USER_COURSE_LIST *u_head, const char *course, int *count)
{
    P_NODE *head, *ptr;
    CONFIG_STRUCT conf;
    SURVEY_USER_COURSE *user_ptr, *new_ptr; 
    
    read_configuration_file(course, &conf);
    head = build_option_person_list(&conf);
    for(ptr = head; ptr; ptr = ptr->next)
    {
      user_ptr = get_one_user_course(u_head, ptr);
      
      if(user_ptr) 
      {
	   user_ptr->course_node_current->next = (COURSE_LIST_NODE *)malloc(sizeof(COURSE_LIST_NODE));
	   user_ptr->course_node_current = user_ptr->course_node_current->next;
	   strncpy(user_ptr->course_node_current->crs, course, MAX_COURSE_NO +1);
	   user_ptr->course_node_current->next = 0;
       }
       else
       {
	 new_ptr = (SURVEY_USER_COURSE *)malloc(sizeof(SURVEY_USER_COURSE ));
	 strncpy(new_ptr->username, ptr->data.username, MAX_USERNAME +1);
	 new_ptr->group = ptr->data.group;
	 new_ptr->next =0;
	 new_ptr->course_node_head = (COURSE_LIST_NODE *)malloc(sizeof(COURSE_LIST_NODE));
	 strncpy(new_ptr->course_node_head->crs, course, MAX_COURSE_NO +1);
	 new_ptr->course_node_head->next =0;
	 new_ptr->course_node_current =  new_ptr->course_node_head;
      
	 if(!u_head->head)
	 {
	    u_head->head = new_ptr;
	    u_head->current = u_head->head;
	 }
	 else
	 {
	   u_head->current->next = new_ptr;
	   u_head->current = u_head->current->next;
	 }
	 *count = *count +1;
       }
    }
  
    free_option_person_list(head);
    return u_head;

}
       	
void
free_user_survey_list(SURVEY_USER_COURSE *head)
{
   SURVEY_USER_COURSE *ptr;
   while( head)
   {
      ptr = head->next; 
      if(head->course_node_head)
	     super_free_course_list(head->course_node_head);
      free(head);
      head = ptr;
   }
}



int
get_course_count(DEL_COURSE_NODE  *head)
{
    int count = 0;
    DEL_COURSE_NODE *ptr;
    for(ptr = head; ptr; ptr=ptr->next)
	    count++;
    return count;
}




DEL_COURSE_NODE *
read_parameters(int *is_admin, char *key,  char *count)
{
   char temp[12];
   DEL_COURSE_NODE  *head;

   cs_get_required_parameter ("admin", temp, 11);
   *is_admin = atoi(temp)? 1 : 0;
   
   cs_get_required_parameter ("id", key, MAX_KEY);
   cs_get_required_parameter ("count", count, MAX_PATH );
   head = build_selected_course_list();                 /* shared_super_util.c */
   return head;
}




   
void
process_one(const char *file_base, 
		INDIV_SURVEY_RECORD *ind_data, 
		COURSE_LIST_NODE *head, TAKERS takers, GROUP_TYPE group, int *process_count)
{
  FILE *fp;
  char file[MAX_PATH +1];
  COURSE_LIST_NODE *ptr;

  if(takers == ALL || takers == STUDENT || 
		  (takers == TEACHERS && group == FACULTY) ||
		  (takers == STUDENTS_ONLY && group == STUDENT))
  {
    *process_count = *process_count +1;		  
    snprintf(file, MAX_PATH +1, "%s/%s", file_base, SURVEY_DELIVER_INFO_FNAME);
    fp = fopen(file, "a+");
    if(!fp)
       cs_critical_error( ERR_FOPEN_WRITE_FAILED, "");
    get_exclusive_lock(fileno(fp), 1);
    
    if (fwrite (ind_data, sizeof (INDIV_SURVEY_RECORD), 1, fp) != 1)
	              cs_critical_error (ERR_FWRITE_FAILED, "");
    release_lock(fileno(fp));
     fclose (fp);
      snprintf(file, MAX_PATH +1, "%s/%s_txt", file_base, ind_data->record.id);
      fp = fopen(file, "w");
      if(!fp)
         cs_critical_error( ERR_FOPEN_WRITE_FAILED, "");
      for(ptr=head; ptr; ptr = ptr->next)
         fprintf(fp, "%s\n", ptr->crs);

      fclose(fp);
  }

}

void
update_central_info(const char *file_base, DEL_COURSE_NODE  *head, CENTRAL_SURVEY_RECORD *data, const char *title)
{
  int course_count;
  DEL_COURSE_NODE *ptr;
  FILE *fp;
  char file[MAX_PATH +1];

  snprintf(file, MAX_PATH +1, "%s/%s", file_base,SURVEY_DELIVER_INFO_FNAME); 
  course_count = get_course_count(head);
  fp = fopen(file, "r+");
  if(!fp)
       cs_critical_error( ERR_FOPEN_WRITE_FAILED, "");
  if(fread(data, sizeof(CENTRAL_SURVEY_RECORD), 1, fp) != 1)
         cs_critical_error (ERR_FOPEN_READ_FAILED, "");

   strncpy(data->record.title, title, MAX_SURVEY_TITLE +1);
   data->record.course_count = course_count;
   if (fseek(fp,0,SEEK_SET))
         cs_critical_error (ERR_CANT_CREATE_NEW_KEY, "");
    if (fwrite (data, sizeof (CENTRAL_SURVEY_RECORD), 1, fp) != 1)
	 cs_critical_error (ERR_FWRITE_FAILED, "");
   fclose(fp);
   snprintf(file, MAX_PATH +1, "%s/%s_txt", file_base,data->record.id); 
   fp = fopen(file, "w");
   if(!fp)
       cs_critical_error( ERR_FOPEN_WRITE_FAILED, "");
   
    for(ptr = head; ptr; ptr = ptr->next)
    {
       if(strcmp(ptr->del_id, " ") !=0)
          fprintf(fp, "%s\n", ptr->del_id);
    }
    fclose(fp);
}

void
process_all(SURVEY_USER_COURSE_LIST *u_head, CENTRAL_SURVEY_RECORD *ctr_data, int *process_count)
{
    INDIV_SURVEY_RECORD data;
    char base[MAX_PATH +1];
    SURVEY_USER_COURSE *ptr;
    
    strncpy(data.record.id, ctr_data->record.id, MAX_PATH +1);
    strncpy(data.record.title, ctr_data->record.title, MAX_SURVEY_TITLE +1);
    data.record.sent_time = ctr_data->record.sent_time;
    data.record.release_time = ctr_data->record.release_time;
    data.record.unrelease_time = ctr_data->record.unrelease_time;
    data.record.results_time = ctr_data->record.results_time;
    data.record.course_count =0;
    data.record.save_courseinfo = ctr_data->record.save_courseinfo;

    for(ptr = u_head->head; ptr; ptr = ptr->next)
    {
      snprintf(base, MAX_PATH +1, "../%s/%c/%s/%s",
	USERS_DIR, sub_dir_name(ptr->username), ptr->username, SURVEY_DIR);
      if(!test_file_exist(base))
       {
            if(mkdir(base, 0770))
             cs_critical_error(ERR_CANT_OPEN_NEWS_DIR, "");
       }
     if(ctr_data->takers == ALL)
        data.store_result = 1;
     else if(ctr_data->takers == STUDENTS || ctr_data->takers == STUDENTS_ONLY)
     {
	if(ptr->group != FACULTY)
           data.store_result = 1;
	else
           data.store_result = 0;

     }
     else
     {
	if(ptr->group == FACULTY)
           data.store_result = 1;
	else
           data.store_result = 0;
     }
      process_one(base, &data, ptr->course_node_head , ctr_data->takers, ptr->group, process_count);
    }
}
      

SURVEY_INFO *
get_deliver_survey_info( const char *count, SESSION *user)
{
    SURVEY_INFO *de_info = 0;
    SURVEY_INFO_LIST *list;
    char file[MAX_PATH +1];
    char survey_base[MAX_PATH +1];

    get_survey_base(user, survey_base);
    snprintf(file, MAX_PATH+1, "%s/%s",survey_base, SURVEY_INFO_FNAME);
    list = survey_info_parser(file);
    if(list)
    {
       list->current = list->head;
       while(list->current)
       {
          if( !strcmp(list->current->id, count))
          {
            de_info = (SURVEY_INFO *)malloc(sizeof(SURVEY_INFO));
            de_info = initialize_survey_info(de_info);
             de_info->id = malloc_str(list->current->id);
             de_info->state = malloc_str(list->current->state);
             de_info->title = malloc_str(list->current->title);
             de_info->create_time = malloc_str(list->current->create_time);
             de_info->finish_time = malloc_str(list->current->finish_time);
             de_info->release_time = malloc_str(list->current->release_time);
             de_info->close_time = malloc_str(list->current->close_time);
             de_info->author_id = malloc_str(list->current->author_id);
             de_info->author_name = malloc_str(list->current->author_name);
             de_info->survey_domain = malloc_str(list->current->survey_domain);
             break;
           }
        list->current = list->current->next;
      }
    }
   else
      de_info = 0;
    free_survey_info_list(list);
    return de_info;
}
void
write_total_taker_to_result(const char *count, int total, SESSION *user)
{
    char file[MAX_PATH +1];
    char survey_path[MAX_PATH +1];
    FILE *fp;

    get_survey_path(user, survey_path, count);
    snprintf(file, MAX_PATH +1, "%s/%s",survey_path, SURVEY_RESULT_FNAME);
    fp = fopen(file, "w");
    if(!fp)
        cs_critical_error(ERR_FOPEN_WRITE_FAILED, "");
      fprintf(fp, "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?>\n");
      fprintf(fp, "<records>\n");
      fprintf(fp, "  <expect_takers>%d</expect_takers>\n", total);
      fprintf(fp, SURVEY_RESULT_END_TAG);
      fclose(fp);
}




void
do_action(const char *count,  SESSION *user,  DEL_COURSE_NODE *head)
{
    SURVEY_INFO *info;
    CENTRAL_SURVEY_RECORD ctr_data;
    char file[MAX_PATH +1];
    DEL_COURSE_NODE *ptr;
    SURVEY_USER_COURSE_LIST *u_head ;
    int total = 0;
   
  
    update_survey_info_state(user,  count, SURVEY_STATE_REL, "", "");
    info = get_deliver_survey_info( count, user);

    u_head = (SURVEY_USER_COURSE_LIST *)malloc(sizeof(SURVEY_USER_COURSE_LIST));
    u_head->head =0;
    u_head->current =0;

    if(info)
    {
      get_survey_path(user, file, count);
      strtrm(info->title);
      update_central_info(file, head, &ctr_data, info->title);
     
      for(ptr = head; ptr; ptr = ptr->next)
      {
          u_head =build_survey_user_course_list(u_head, ptr->del_id, &total);
      }
      total = 0; 
      process_all(u_head, &ctr_data, &total);

      write_total_taker_to_result( count,  total, user);
    }
    else
      cs_critical_error(ERR_DATA_IS_NOT_AVAILABLE, "");
    if(u_head)
      free_user_survey_list(u_head->head);
   if(info)
     free_survey_info(info);
   free(u_head);
}




/*void free_del_list(DEL_COURSE_NODE *head)
{
    DEL_COURSE_NODE *ptr;
    while(head)
   {
         ptr = head->next;
         if(head->del_id)
         free(head->del_id);
        if(head->del_info)
           free(head->del_info);
        free(head);
        head = ptr;
     }

} */

int 
main()
{
   int is_admin;
   char count[MAX_PATH +1];
   char key[MAX_KEY +1];
   SESSION user;
   DEL_COURSE_NODE *head;

   cs_cgi_init();
   head = read_parameters(&is_admin, key,  count);
   verify_key_path(&user, key, is_admin);
   do_action( count,  &user,  head);
   printf("Location: %s?admin=%d&id=%s\n\n", 
		   "survey_read_info", is_admin, key);
   free_del_list(head);
   cs_cgi_destroy();
   return 0;
}
