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

#include "global.h"
#include "custom.h"

SESSION user;
CONFIG_STRUCT conf;		/* the configuration read from config file */


#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_hotpot_parser.h"
#include "manhat-lib/shared_hotpot_exam_util.h"
#include "manhat-lib/shared_server_string.h"
#include "manhat-lib/shared_access.h"


static void
read_parameters (char *course, char *key, char *sender,  char *info_fname, long *offset)
{
  char tmp[25];

  cs_get_required_parameter ("crs", course, MAX_FILENAME);	/* shared_cgi_util.c */
  cs_get_required_parameter ("id", key, MAX_KEY);
  cs_get_required_parameter ("sender", sender, MAX_USERNAME);
  cs_get_required_parameter ("inf", info_fname, MAX_FILENAME);  
  cs_get_required_parameter  ("loc", tmp, 24);
  *offset = atol(tmp);
  
}



 


static void
do_header(const char *symlink_fname)
{
 char server_string[MAX_PATH + 1];
 char url[MAX_PATH + 1];

 get_server_string(server_string, MAX_PATH + 1);   /* shared_server_string.c */
 snprintf(url, MAX_PATH +1, "%s%slinks/%s/", server_string, IMAGE_PATH, symlink_fname);
 cs_set_value("base_url", url); 
 
 
 if(quiz_data.pg_bg_color)
     cs_set_value("bg_color", quiz_data.pg_bg_color); 
 if(quiz_data.text_color)
     cs_set_value("text_color", quiz_data.text_color);
 if(quiz_data.link_color)
     cs_set_value("link_color", quiz_data.link_color); 
 if(quiz_data.vlink_color)
     cs_set_value("vlink_color", quiz_data.vlink_color);
 if(quiz_data.font_face)    
     cs_set_value("font_face", quiz_data.font_face);    
 if(quiz_data.ex_bg_color)
     cs_set_value("ex_bg_color", quiz_data.ex_bg_color);    
}




static void
print_string(char *string, const char *prefix)
{
 #define MAX_TMP_NAME 30
 char *ptr;
 int line_num =0;
 int chars_added = 0;
 int j =0;
 char name[MAX_TMP_NAME];
 char *buf =0;

 buf = (char*)malloc(sizeof(char) * (strlen(string) + 1)); 
 if(!buf)
    cs_critical_error(ERR_MALLOC_FAILED, "");
 
 *buf = '\0';
 
 for(ptr=string; *ptr; ptr++)
  {
   if(*ptr == '\n')
    {
	buf[j] = *ptr;
	buf[j+1] = '\0';
	snprintf(name, MAX_PATH +1, "%s.line.%d", prefix, line_num);
        cs_set_value(name, buf);
	buf[0] = '\0';
	j = 0;
	line_num++;
	chars_added = 0;
    }
   else
     {
	buf[j] = *ptr;
	j++;
	buf[j] = '\0';
	chars_added = 1;
     }
  }



 if(chars_added && strlen(buf))
 {
	snprintf(name, MAX_PATH +1, "%s.line.%d", prefix, line_num);
	cs_set_value(name, buf);
 }
 free(buf);
 #undef MAX_TMP_NAME 
}






static void
do_instructions()
 {
  if(quiz_data.title)
   { 
      cs_set_value("quiz.title", quiz_data.title);
      if(quiz_data.title_color)
        cs_set_value("quiz.title_color", quiz_data.title_color);
   }   
   
  if(quiz_data.sub_title)
    print_string(quiz_data.sub_title, "quiz.sub_title");
      
  if(quiz_data.instructions)
    print_string(quiz_data.instructions, "quiz.instruction");
       
       
 }
 



/* hotpot_answer_letters is global in shared_hotpot_parser.h */
static void
do_questions()
 {

  #define MAX_TMP_NAME 40
  int q,a =0;
  QUESTION_NODE *q_ptr;
  ANSWER_NODE *a_ptr; 
  char url[MAX_PATH +1];
  char name[MAX_TMP_NAME];
  char temp[MAX_TMP_NAME];

    
  snprintf(url, MAX_PATH +1, "%s/%s",ALIAS, "hotpot_exam_score");
  cs_set_value("action", url);
  
 for(q_ptr = quiz_data.head, q=0 ; q_ptr; q_ptr=q_ptr->next, q++)
 {
   snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.body", q);
   print_string(q_ptr->question, name);

   snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.type", q);
   switch(q_ptr->question_type)
    {
     case 0:  cs_set_value(name,"mc"); break;
     case 1:  cs_set_value(name, "short"); break;
     case 2:  cs_set_value(name,"mc_multi"); break;
     default: cs_set_value(name,"unknown"); break;
    } 

  if(q_ptr->question_type == MC)   /* multiple-choice */
   {
    
    for(a_ptr = q_ptr->head, a=0; a_ptr; a_ptr = a_ptr->next, a++)
     {
      if(a >= MAX_HOTPOT_CHOICES)  /* shared_hotpot_parser.h */
           break;      
     snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.mc.%d.letter", q, a);
     snprintf(temp, MAX_TMP_NAME, "%c", hotpot_answer_letters[a]);
     cs_set_value(name, temp);

     /* why are letter and value same ?? */
     snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.mc.%d.value", q, a);
     cs_set_value(name, temp);

     snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.mc.%d.name", q, a);
     snprintf(temp, MAX_TMP_NAME, "q%d", q);
     cs_set_value(name, temp);
     
     snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.mc.%d.answer", q, a);
     cs_set_value(name, a_ptr->answer);

     }
   }
  else 
    if(q_ptr->question_type == MC_MULTI)   /*multiple-select */
    {
     for(a_ptr = q_ptr->head, a=0; a_ptr; a_ptr = a_ptr->next, a++)
      {
      if(a >= MAX_HOTPOT_CHOICES)   /* shared_hotpot_parser.h */
           break;      
     snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.mcmulti.%d.letter", q, a);
     snprintf(temp, MAX_TMP_NAME, "%c", hotpot_answer_letters[a]);
     cs_set_value(name, temp);
     snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.mcmulti.%d.value", q, a);
     cs_set_value(name, temp);
     snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.mcmulti.%d.name", q, a);
     snprintf(temp, MAX_TMP_NAME, "q%d", q);
     cs_set_value(name, temp);
     snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.mcmulti.%d.answer", q, a);
     cs_set_value(name, a_ptr->answer);
      }
    } 
    else  
     if(q_ptr ->question_type == SHORT)
     {
	a=0;
       snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.short.%d.name", q, a);
       snprintf(temp, MAX_TMP_NAME, "q%d", q);
       cs_set_value(name, temp);
     }
         								
    								
 }
 cs_set_int_value("quiz_total", q);
  #undef MAX_TMP_NAME 

}











static void
do_submit( char *course,  char *key,  char *sender,   char *info_fname, 
		long offset, time_t *current_time, int access)
 {
  char temp[MAX_PATH +1];

 
 *current_time = time(NULL);
 if(access != ACCESS_CAPTURE)
 { 
   cs_set_int_value("access", 1);
   cs_set_value("crs", course);
   cs_set_value("id", key);
   cs_set_value("sender", sender);
   cs_set_value("inf", info_fname);
   snprintf(temp, MAX_PATH, "%ld", (long)*current_time);
   cs_set_value("test", temp);
   snprintf(temp, MAX_PATH, "%ld", offset);
   cs_set_value("loc", temp);
 }
                                      
}  
 
 
 
 




static void
show_quiz( char *course,  char *key,  char *sender, 
			const char *dirname,  char *info_fname, long offset, 
	                        const SESSION *user, const CONFIG_STRUCT *conf, time_t *current_time)
{
 char symlink_fname[MAX_FILENAME + 1];
 
 create_hotpot_exam_symlink(conf->course_path, sender, dirname, 
                         user, course, symlink_fname, conf->access); /*shared_hotpot_exam_util.c */
 do_header(symlink_fname);
 do_instructions();
 do_questions();
 do_submit(course,key,sender,info_fname, offset, current_time, conf->access);
}  




/* writes current_time to the beginning of
** the hotpot score file, but only if the 
** file is new, or if the time that's stored
** in the file is 0.
** These restrictions prevent someone from 
** reloading the web page to reset the timer
**/
static void
write_viewed_flag(time_t current_time, SESSION *user, 
                     const char *sender_username, const char *info_fname, const char *course_path)
{
 char path[MAX_PATH + 1];
 FILE *fp;
 int fd;
 time_t last_time;
 int new_file = 0;

 get_hotpot_score_path(course_path, user->username, sender_username,info_fname, path); /* shared_hotpot_exam_util.c */
  
 fp = fopen(path,"r+");
 if(!fp)
   {
    fp = fopen(path, "w");
    if(!fp)
          cs_critical_error(ERR_FOPEN_WRITE_FAILED, path);
   new_file = 1;       
   }       
 fd = fileno(fp);
 get_exclusive_lock(fd,1);   /* shared_lock.c */  
 
 if(new_file)
    last_time = 0;
 else
   {
    if(fread(&last_time, sizeof(time_t), 1, fp) != 1)
        cs_critical_error(ERR_FREAD_FAILED, path);
    if(fseek(fp, 0,SEEK_SET))
        cs_critical_error(ERR_FSEEK_FAILED, path);
  }      
           
 if(!last_time)
  {
   if(fwrite(&current_time, sizeof(time_t),1, fp) != 1)
       cs_critical_error(ERR_FWRITE_FAILED, path);
  }     
 release_lock(fd);   /* shared_lock.c */   
 fclose(fp);
}


 					


int
main (void)
{
  char course[MAX_PATH + 1];	     /* from crs=? command line */
  char key[MAX_KEY + 1];	     /* from id=? command line */
  char sender[MAX_USERNAME + 1];     /* from user=? command line */
  char info_fname[MAX_FILENAME + 1]; /* from info=? cmd line */
  long offset;                       /* from loc=? cmd line */

  char source_path[MAX_PATH + 1];
  char dirname[MAX_FILENAME + 1];
  time_t current_time;
  int can_write;                    /* can this user write to this course? */

  cs_cgi_init();                    /* shared_cs_util.c */
  
  read_parameters (course, key, sender, info_fname, &offset);
  read_configuration_file (course, &conf);	/* shared_util.c */
  validate_key (key, &user, &conf);	/* shared_util.c */

  can_write = has_write_permission(&user, &conf);   /* shared_access.c */

  if( (user.group == STUDENT)  && !can_write)   /* don't allow students without write access to see the exam */
      access_denied_error();                    /* shared_access.h */
     
  get_hotpot_exam_source_fname (source_path, dirname, conf.course_path, sender, info_fname);  /* shared_hotpot_exam_util.c */

  if(parse_hotpot_file(source_path))   /* shared_hotpot_parser.c */
     cs_critical_error(ERR_ERROR_PARSING_HOTPOT_FILE, "");
    
  show_quiz(course,key,sender,dirname, info_fname, offset, &user, &conf, &current_time);

  free_quiz_data();     /* shared_hotpot_parser.c */  
  
  if(user.group == STUDENT)
     write_viewed_flag(current_time, &user, sender, info_fname, conf.course_path);
  else
     cs_set_int_value("teacher_test_exam", 1);

  cs_set_course_info(&conf);   /* shared_cs_util.c */
  cs_set_current_time();       /* shared_cs_util.c */
  cs_set_server_name();        /* shared_cs_util.c */
  cs_cgi_display("hotpot_exam_present", 1);   /* shared_cs_util.c */
  cs_cgi_destroy();                           /* shared_cs_util.c */
  return 0;


}












