#include <stdio.h>
#include <sys/stat.h>		/* for stat() */
#include <string.h>
#include <ctype.h>
#include <time.h>


#include "global.h"
#include "custom.h"		/* for date FORMAT strings */
#include "survey.h"


#include "manhat-lib/shared_util.h"
#include "manhat-lib/shared_cs_util.h"
#include "manhat-lib/shared_news_util.h"
#include "manhat-lib/shared_lock.h"
#include "manhat-lib/shared_person_list.h"

typedef struct news_person_node
{
  NEWS_PERSON data;
  struct news_person_node *next;
}
NEWS_PERSON_NODE;



static void
read_parameters (char *course, char *key, long *offset)
{

  char tmp[MAX_FILENAME + 1];	/* for holding the long value, length should
				   be long enough, don't you think? */


  cs_get_required_parameter ("crs", course, MAX_PATH);	/* shared_cgi_util.c */
  cs_get_required_parameter ("id", key, MAX_KEY);	/* shared_cgi_util.c */
  cs_get_required_parameter ("loc", tmp, MAX_FILENAME);	/* shared_cgi_util.c */
  *offset = atol (tmp);


}










void
read_release_file(const char *course_path, const char *sender, const char *survey_dir, 
                        SURVEY_RELEASE_RECORD *release)
{
  char path[MAX_PATH + 1];
  FILE *fp;
  
  snprintf(path, MAX_PATH + 1, "%s%s/%s/%s/%s/%s",
        course_path,
        PEOPLE_DIR,
        sender,
        SURVEY_DIR,
        survey_dir,
        SURVEY_RELEASE_FNAME);                        
  fp = fopen(path, "r");
  if(!fp)
     cs_critical_error(ERR_FOPEN_READ_FAILED, "");
  if(fread(release, sizeof(SURVEY_RELEASE_RECORD), 1, fp) != 1)
     cs_critical_error(ERR_FREAD_FAILED, "");
  fclose(fp);
}
     

static NEWS_PERSON_NODE *
free_news_person_list (NEWS_PERSON_NODE *person_head)
{
  NEWS_PERSON_NODE *pptr;

  while (person_head)
    {
      pptr = person_head;
      person_head = person_head->next;
      free (pptr);
    }
  return person_head;  
}


static 
int count_student_respondents(NEWS_PERSON_NODE *respondent_head, P_NODE *roster_head)
{
 int student_count = 0;
 P_NODE *roster_ptr;
 NEWS_PERSON_NODE *resp_ptr;
 
 for(resp_ptr = respondent_head; resp_ptr; resp_ptr = resp_ptr->next)
    {
     for(roster_ptr = roster_head; roster_ptr; roster_ptr = roster_ptr->next)
       if(!strcmp(roster_ptr->data.username, resp_ptr->data.username))
         {
          if(roster_ptr->data.group == STUDENT)
            student_count++;
          break;
         }
      }
      
 return student_count;
}


static void
count_respondents(NEWS_PERSON_NODE *person_head, int *number_respondents, int *total_students, CONFIG_STRUCT *conf)
{
 P_NODE *roster_head;
 
 
 roster_head = build_option_person_list(conf);   /* shared_option_person_list.c */
 *number_respondents = count_student_respondents(person_head, roster_head);
 *total_students = count_students(roster_head);   /* shared_option_person_list.c */
 free_option_person_list(roster_head);           /* shared_option_person_list.c */
}
 



/* reads the inbox file and then the corresponding *.inf file, to get everything
** ready to be displayed
**/
static void
process_inbox_record (long offset, CENTRAL_INBOX_RECORD * inbox,
		      NEWS_INFO * infofile_info,
                      CONFIG_STRUCT *conf, SESSION *user,
                      SURVEY_RELEASE_RECORD *release, char *survey_dir,
                      int *number_respondents, int *total_students)
{
  FILE *fp;
  int fd;
  char infopath[MAX_PATH + 1];
  ATTACHMENT attachment;
  char inbox_path[MAX_PATH + 1];	/* full path to inbox.dat */
  NEWS_PERSON person;
  NEWS_PERSON_NODE *person_head = 0, *pptr = 0;
  
 snprintf(inbox_path,MAX_PATH + 1,"%s%s",central_discussion_path,INBOX_FNAME);
 fp = fopen(inbox_path,"r");
 if (!fp)
    cs_critical_error (ERR_FOPEN_READ_FAILED, "");

 fd = fileno(fp);
 get_shared_lock(fd, 1);                      /* shared_lock.c */


 if (fseek (fp, offset, SEEK_SET))
    cs_critical_error (ERR_FSEEK_FAILED, "");
 if (fread (inbox, sizeof (CENTRAL_INBOX_RECORD), 1, fp) != 1)
    cs_critical_error (ERR_FREAD_FAILED, "");

  release_lock(fd);   /* shared_lock.c */
  fclose (fp);


  /*** now read the info file */
  snprintf (infopath, MAX_PATH + 1, "%s%s/%s/%s/%s", conf->course_path, PEOPLE_DIR,
	    inbox->info.sender,
	    discussion_fname, inbox->info_fname);

  fp = fopen (infopath, "r");
  if (!fp)
    cs_critical_error (ERR_FOPEN_READ_FAILED, "");
  
  fd = fileno(fp);
  get_shared_lock(fd,1);         /* shared_lock.c */
    
  if (fread (infofile_info, sizeof (NEWS_INFO), 1, fp) != 1)
    cs_critical_error (ERR_FREAD_FAILED, "");


  /* read the attachment to extract the name of the survey directory*/

   if (fread (&attachment, sizeof (ATTACHMENT), 1, fp) != 1)
      cs_critical_error (ERR_FREAD_FAILED, "");
   strncpy(survey_dir, attachment.unique_fname, MAX_FILENAME + 1);
   
   read_release_file(conf->course_path, inbox->info.sender, survey_dir, release);

   *number_respondents = 0;
   *total_students = 0;
  /* count the number of respondents */
   if(release->student_view_results || user->group == FACULTY)
    {
      while (fread (&person, sizeof (NEWS_PERSON), 1, fp) == 1)
      {
        if (!person_head)
	 {
	  person_head =
	    (NEWS_PERSON_NODE *) malloc (sizeof (NEWS_PERSON_NODE));
	  if (!person_head)
	    cs_critical_error (ERR_MALLOC_FAILED, "");
	  pptr = person_head;
	 }
        else
	 {
	  pptr->next =
	    (NEWS_PERSON_NODE *) malloc (sizeof (NEWS_PERSON_NODE));
	  if (!pptr->next)
	    cs_critical_error (ERR_MALLOC_FAILED, "");
	  pptr = pptr->next;
	 }
       pptr->data = person;
       pptr->next = 0;
     }
    count_respondents(person_head, number_respondents, total_students, conf);
    person_head = free_news_person_list(person_head);
    }  
   
  release_lock(fd);   /* shared_lock.c */
  fclose (fp);
 
}



 







static void
print_basic_info ( char *sender, NEWS_INFO * infofile_info,
                      SESSION *user, CONFIG_STRUCT *conf, SURVEY_RELEASE_RECORD *release,
                      int number_respondents, int total_students)
{
  char timestring[MAX_TIMESTRING +1];
  char url[MAX_PATH +1];
  char *scaped_subject;

  cs_set_course_info(conf);
  cs_set_current_time();

  cs_html_escape_string(infofile_info->subject, &scaped_subject);
  
  cs_set_value("subject", scaped_subject);
  free(scaped_subject);


  cs_set_value("sender", infofile_info->sender_realname);	

  strftime (timestring, MAX_TIMESTRING, DOW_DATE_TIME_FORMAT,
	      localtime (&(infofile_info->time_sent)) );
   cs_set_value("send_time", timestring);

 /** print result time */
  strftime (timestring, MAX_TIMESTRING, DOW_DATE_TIME_FORMAT,
	      localtime (&(release->results_time)) );
   cs_set_value("release_time", timestring);


  /** can students view results? */

   cs_set_int_value("review_result", release->student_view_results);
   cs_set_int_value("review_survey", release->student_view_again);
   cs_set_int_value("answer_required", release->student_answer_required);


  /* total respondents to-date */
  if((user->group == FACULTY) || (release->student_view_results))
  {
   snprintf(url, MAX_PATH +1, "%d/%d (%.1f %%)",number_respondents, total_students, 
                ((float) number_respondents/total_students) * 100.0);
   cs_set_value("total", url);
  }
}




static
void insert_results_links(const char *sender, const char *info_fname, const char *course, 
                                 const char *key)
{
  char url[MAX_PATH +1];
  
  /* set url to graphs */
  
   snprintf(url, MAX_PATH +1, "%s?crs=%s&amp;id=%s&amp;sender=%s&amp;inf=%s",
                "survey_module_bar_graph", course, key, sender, info_fname);
   cs_set_value("graph_url", url);

  
  /* set url to tables */
  
   snprintf(url, MAX_PATH +1, "%s?crs=%s&amp;id=%s&amp;sender=%s&amp;inf=%s",
                "survey_module_table", course, key, sender, info_fname);
   cs_set_value("table_url", url);
  
  /* set url to csv file */  

   snprintf(url, MAX_PATH +1, "%s?crs=%s&amp;id=%s&amp;sender=%s&amp;inf=%s&amp;csv=yes&amp;ext=.csv",
                "survey_module_table", course, key, sender, info_fname);
   cs_set_value("csv_url", url);

}


static void print_results_not_available(time_t results_time)
{
   char timestring[MAX_TIMESTRING + 1];
 
    strftime (timestring, MAX_TIMESTRING, DOW_DATE_TIME_FORMAT,
	      localtime (&results_time));
   cs_set_value("result_time", timestring);

}



static void
display_info (char *course, char *key, long offset,  CONFIG_STRUCT *conf, SESSION *user)
{
  CENTRAL_INBOX_RECORD inbox;
  NEWS_INFO infofile_info;
  SURVEY_RELEASE_RECORD release;
  char survey_dir[MAX_FILENAME + 1];
  time_t now;
  int number_respondents, total_students;
  
  
  process_inbox_record (offset, &inbox, &infofile_info, conf, user,
                                 &release, survey_dir, &number_respondents, &total_students);

  /* print the header info */
  print_basic_info (inbox.info.sender, &infofile_info,  user, conf, &release, number_respondents, total_students);
  
  now = time(NULL);
  
  if(release.student_view_results || (user->group == FACULTY))
   {
    cs_set_int_value("show_results", 1);
    if(release.results_time <= now)
      insert_results_links(inbox.info.sender, inbox.info_fname, course, key); 
    else
      print_results_not_available(release.results_time);
   }     

}











int
main (void)
{
  char course[MAX_PATH + 1];	/* from crs=? command line */
  char key[MAX_KEY + 1];	/* from id=? command line */
  long offset;			/* from loc=? command line */
  SESSION user;
  CONFIG_STRUCT conf;		/* the configuration read from config file */

  cs_cgi_init();

  read_parameters (course, key, &offset);
  read_configuration_file (course, &conf);	/* shared_util.c */
  validate_key (key, &user, &conf);	/* shared_util.c */
  
  set_discussion_names (conf.course_path, user.username, SURVEYS);	/* shared_news_util.c */
  display_info (course, key, offset, &conf, &user);
  cs_cgi_display("survey_info", 1);
  cs_cgi_destroy();
  return 0;
}
