#include "shared_grade_book_util.h"
#include "shared_grade_book_db.h"
#include "shared_util.h"
#include "shared_file_util.h"
#include "shared_time.h"
#include "shared_strtrm.h"

int check_spe_char( char *val)
{
     char str[] = "&<>@@$%*!?/;,:#{}[]='`";
     int i, len;
     char *ptr =0;

     len = strlen(val);

     for(i = 0; i< len; i++)
     {
        ptr = strchr(str, val[i]);
        if(ptr)
	   return 0;	
     }
     return 1;
}

int check_float_number(const char *val)
{
    int i, len, dot =0;


    if(val[0] == '.')
      return 0;
    len = strlen(val);
    for(i =0; i<len; i++)
   {
        if((!isdigit(val[i]) && val[i] != '.'))
               return 0;
        if(val[i] == '.')
          dot++;
    }
    if(dot > 1)
        return 0;
    return 1;
}

void free_scale_list(SCALE_LIST *list)
{
    SCALE *ptr;

    if(list)
    {
      while(list->head)
      {
         ptr = list->head->next;
         free(list->head);
         list->head = ptr;
      }
    free(list);
    }      
}

void free_category_list(CATEGORY_LIST *list)
{
   CATEGORY *ptr;

   if(list)
   {
         while(list->head)
	 {
             ptr = list->head->next;
	     free(list->head);
	     list->head = ptr;
	 }
         free(list);
   } 
}
void free_item_list(ITEM_LIST *list)
{
   ITEM *ptr;

   if(list)
   {
         while(list->head)
	 {
             ptr = list->head->next;
	     if(list->head->grades)
                 free_grade_list(list->head->grades);
             if(list->head->letters)
                 free_letter_grade_list(list->head->letters);

	     free(list->head);
	     list->head = ptr;
	 }
         free(list);
   } 
}
void free_letter_grade_list(LETTER_GRADE_LIST *list)
{
   LETTER_GRADE *ptr;

   if(list)
   {
         while(list->head)
	 {
             ptr = list->head->next;
	     free(list->head);
	     list->head = ptr;
	 }
         free(list);
   }
}
void free_grade_list(GRADE_LIST *list)
{
   GRADE *ptr;

   if(list)
   {
         while(list->head)
	 {
             ptr = list->head->next;
	     if(list->head->comment)
		    free(list->head->comment);
	     free(list->head);
	     list->head = ptr;
	 }
         free(list);

   }
}
void free_total_grade_list(TOTAL_GRADE *head)
{
    TOTAL_GRADE *ptr;
    if(head)
    {
	while(head)
	{
	    ptr = head->next;
	    free(head);
	    head = ptr;
	}
    }
}


void set_cat_list_values()
{
#define MAX_TMP 40
   CATEGORY *ptr;
   char name[MAX_TMP];
   char temp[MAX_TMP];
   int i = 1;

   cs_set_int_value("cat_name_len",MAX_CAT_LEN);
   for(ptr = global_cat_list->head; ptr; ptr = ptr->next)
   {
      snprintf(name, MAX_TMP, "categories.%d.cat_name", i);
      cs_set_value(name, ptr->cat_name);
      snprintf(name, MAX_TMP, "categories.%d.cat_id", i);
      cs_set_int_value(name, ptr->cat_id);
      snprintf(name, MAX_TMP, "categories.%d.cat_weight", i);
      snprintf(temp, MAX_TMP, "%4.*f", test_precision(ptr->weight), ptr->weight);
      strtrm(temp);
      cs_set_value(name, temp);
      snprintf(name, MAX_TMP, "categories.%d.cat_drop", i);
      cs_set_int_value(name, ptr->drop_lowest);
      if(ptr->weight == 0)
      {
         snprintf(name, MAX_TMP, "categories.%d.cat_ungraded", i);
         cs_set_int_value(name, 1);

      }
      snprintf(name, MAX_TMP, "categories.%d.number_members", i);
      cs_set_int_value(name, ptr->number_members);
      snprintf(name, MAX_TMP, "categories.%d.number_graded_items", i);
      cs_set_int_value(name, ptr->number_graded_items);
      snprintf(name, MAX_TMP, "categories.%d.number_hided_items", i);
      cs_set_int_value(name, ptr->hided_items);
      i++;

   } 
   cs_set_int_value("number_categories", i -1);

#undef MAX_TMP 
}
void set_item_list_values(int flag, int is_student_db)
{
#define MAX_TMP 40
   ITEM *ptr =0;
   char name[MAX_TMP];
   char temp[MAX_TMP];
   int i = 1;
   struct tm *due_time;

   for(ptr = global_item_list->head; ptr; ptr = ptr->next)
   {
    if( (is_student_db == 0) || (is_student_db && !strcmp(ptr->hide, "no")))
    {
		  
     snprintf(name, MAX_TMP, "items.%d.item_id", i);
     cs_set_int_value(name, ptr->item_id);

     snprintf(name, MAX_TMP, "items.%d.item_name", i);
     cs_set_value(name, ptr->item_name);
     
     if(strcmp(ptr->is_letter_grade, "no") ==0)
     {
       snprintf(name, MAX_TMP, "items.%d.item_points", i);
       snprintf(temp, MAX_TMP, "%4.*f", test_precision(ptr->points), ptr->points);
       strtrm(temp);
       cs_set_value(name, temp);

     }
     due_time = localtime(&(ptr->due_date));
     snprintf(temp, MAX_TMP, "%s%d/%s%d/%d", 
		     (due_time->tm_mon + 1) < 10 ? "0" :"",
		     due_time->tm_mon +1,
		     due_time->tm_mday  < 10 ? "0" :"",
		     due_time->tm_mday,
		     due_time->tm_year +1900
		     );
     snprintf(name, MAX_TMP, "items.%d.due_date", i);
     cs_set_value(name, temp);
     set_hour_minute_ampm(due_time, name); /* shared_time.c */

     
     snprintf(name, MAX_TMP, "items.%d.extra_credit", i);
     cs_set_value(name, ptr->extra_credit);

     snprintf(name, MAX_TMP, "items.%d.is_letter_grade", i);
     cs_set_value(name, ptr->is_letter_grade);

     snprintf(name, MAX_TMP, "items.%d.grade_entered", i);
     cs_set_value(name, ptr->grade_entered);

     snprintf(name, MAX_TMP, "items.%d.hide", i);
     cs_set_value(name, ptr->hide);

     snprintf(name, MAX_TMP, "items.%d.cat_id", i);
     cs_set_int_value(name, ptr->cat_id);
     
     if(flag)
     { 
       if(strlen(ptr->min))
       {
         snprintf(name, MAX_TMP, "items.%d.min", i);
	 cs_set_value(name, ptr->min);

       }
       if(strlen(ptr->max))
       {
         snprintf(name, MAX_TMP, "items.%d.max", i);
	 cs_set_value(name, ptr->max);
       }
       if(strlen(ptr->avg))
       {
         snprintf(name, MAX_TMP, "items.%d.avg", i);
	 cs_set_value(name, ptr->avg);
       }
     }
     i++;
    }
   }
   cs_set_int_value("number_items", i-1);

#undef MAX_TMP 
}

void  set_person_list_values(P_NODE *head, SESSION *user)
{
  #define MAX_TMP 40
    P_NODE *ptr;
    char name[MAX_TMP];
    int i=0;
    char *username;

    username = hdf_get_value(global_cgi->hdf, "Query.username", "");
    if(user->group == STUDENT)
          username = malloc_str(user->username);

    for(ptr = head; ptr; ptr = ptr->next)
    {
       if(ptr->data.group != FACULTY && *(ptr->data.realname) != '*')
       {
	if(user->group == FACULTY && strlen(username) ==0)
	{
	  snprintf(name, MAX_TMP, "std.%d.username", i);
	  cs_set_value(name, ptr->data.username);
	  snprintf(name, MAX_TMP, "std.%d.realname", i);
	  cs_set_value(name, ptr->data.realname);
	  snprintf(name, MAX_TMP, "std.%d.id", i);
	  cs_set_value(name, ptr->data.id);

          i++;
	}
	else
	{
            if(strcmp(username, ptr->data.username) ==0)
	    {
	       snprintf(name, MAX_TMP, "std.%d.username", i);
	       cs_set_value(name, ptr->data.username);
	       snprintf(name, MAX_TMP, "std.%d.realname", i);
	       cs_set_value(name, ptr->data.realname);
	       snprintf(name, MAX_TMP, "std.%d.id", i);
	       cs_set_value(name, ptr->data.id);
               i++;

	    }
	}
       }
    }
    cs_set_int_value("number_students", i);    

    
  #undef MAX_TMP 
}

void    set_letter_grades_value()
{
   #define MAX_TMP_LEN 40
   LETTER_GRADE *ptr;
   char name[MAX_TMP_LEN];
   char temp[MAX_TMP_LEN];
   int i= 1;

   for(ptr = global_letter_grades->head; ptr; ptr = ptr->next)
   {
      snprintf(name, MAX_TMP_LEN, "letter.%d.letter_id", i);	
      cs_set_int_value(name, ptr->letter_id);
      snprintf(name, MAX_TMP_LEN, "letter.%d.letter", i);	
      cs_set_value(name, ptr->letter);
      snprintf(name, MAX_TMP_LEN, "letter.%d.points", i);	
      snprintf(temp, MAX_TMP_LEN, "%4.*f", test_precision(ptr->points), ptr->points);
      strtrm(temp);
      cs_set_value(name, temp);
      snprintf(name, MAX_TMP_LEN, "letter.%d.item_id", i);	
      cs_set_int_value(name, ptr->item_id);

      i++;
   }
    cs_set_int_value("number_letter_grades", i-1);


   #undef MAX_TMP_LEN 
}

void set_current_grade_list_values()
{
   #define MAX_TMP_LEN 40
   char name[MAX_TMP_LEN];
   GRADE *ptr;
   char temp[MAX_TMP_LEN];

   for(ptr = global_grade_list->head; ptr; ptr = ptr->next)
   {
	snprintf(name, MAX_TMP_LEN, "score.%s.%d.score", ptr->username, ptr->item_id);
        snprintf(temp, MAX_TMP_LEN, "%4.*f", test_precision(ptr->score), ptr->score);
        strtrm(temp);	
	cs_set_value(name, temp);
	snprintf(name, MAX_TMP_LEN, "score.%s.%d.excuse", ptr->username, ptr->item_id);
	cs_set_value(name, ptr->excuse);
	snprintf(name, MAX_TMP_LEN, "score.%s.%d.pending", ptr->username, ptr->item_id);
	cs_set_value(name, ptr->pending);
	snprintf(name, MAX_TMP_LEN, "score.%s.%d.comment", ptr->username, ptr->item_id);
	cs_set_value(name, ptr->comment);
	snprintf(name, MAX_TMP_LEN, "score.%s.%d.letter_id", ptr->username, ptr->item_id);
	cs_set_int_value(name, ptr->letter_id);
      

   }

   #undef MAX_TMP_LEN 
}

void set_score_log_values()
{
   #define MAX_TMP_LEN 40
   char name[MAX_TMP_LEN];
   GRADE *ptr;
   char temp[MAX_TMP_LEN];
   int i = 0;
   char timestring[MAX_TIMESTRING +1];



   for(ptr = global_grade_list->head; ptr; ptr = ptr->next)
   {
	if(strcmp(ptr->is_letter_grade, "no" ) == 0)
	{
	   if(ptr->score >= 0)
	   {
	      snprintf(name, MAX_TMP_LEN, "score.%d.score", i);
              snprintf(temp, MAX_TMP_LEN, "%4.*f", test_precision(ptr->score), ptr->score);
              strtrm(temp);
	      cs_set_value(name, temp);
	      snprintf(name, MAX_TMP_LEN, "score.%d.comment", i);
	      cs_set_value(name, ptr->comment);
	      strftime (timestring, MAX_TIMESTRING, DOW_DATE_TIME_FORMAT,localtime (&(ptr->timestamp)));
	      snprintf(name, MAX_TMP_LEN, "score.%d.timestamp", i);
	      cs_set_value(name, timestring);
              i++;
	   }
	}
	else
	{
          if(ptr->letter_id >0)
	  { 
	   snprintf(name, MAX_TMP_LEN, "score.%d.letter", i);
	   cs_set_value(name, ptr->letter);

	   snprintf(name, MAX_TMP_LEN, "score.%d.comment", i);
	   cs_set_value(name, ptr->comment);
	   strftime (timestring, MAX_TIMESTRING, DOW_DATE_TIME_FORMAT,localtime (&(ptr->timestamp)));
	   snprintf(name, MAX_TMP_LEN, "score.%d.timestamp", i);
	   cs_set_value(name, timestring);



           i++;
	  }
	}
   }

   #undef MAX_TMP_LEN 
}

int read_grade_book_conf(CONFIG_STRUCT *conf, GRADE_BOOK_CONFIGURE *grade_conf)
{
    char path[MAX_PATH +1];
    FILE *fp;

    snprintf(path, MAX_PATH +1, "%s%s/%s", conf->course_path, GRADE_BOOK_DIR, GRADE_CAL_CONF_FNAME);
    if(!file_exists(path))
      return 0;

    fp = fopen(path, "r");
    if(!fp)
      cs_critical_error(ERR_FOPEN_READ_FAILED, "grade_book_final read grade book conf");
    if(fread(grade_conf, sizeof(GRADE_BOOK_CONFIGURE), 1, fp) != 1)
      cs_critical_error(ERR_FREAD_FAILED, "grade_book_final read grade book conf");
    fclose(fp);
    return 1;
}

int read_release_conf(CONFIG_STRUCT *conf, RELEASE_CONF *release_conf)
{
    char path[MAX_PATH +1];
    FILE *fp;

    snprintf(path, MAX_PATH +1, "%s%s/%s", conf->course_path, GRADE_BOOK_DIR, GRADE_BOOK_RELEASE_CONF_FNAME);
    if(!file_exists(path))
      return 0;

    fp = fopen(path, "r");
    if(!fp)
      cs_critical_error(ERR_FOPEN_READ_FAILED, "grade_book_final read grade book conf");
    if(fread(release_conf, sizeof(RELEASE_CONF), 1, fp) != 1)
      cs_critical_error(ERR_FREAD_FAILED, "grade_book_final read grade book conf");
    fclose(fp);
    return 1;
}

int test_precision(float aNumber)
{
    float diff;

    diff = aNumber - (int)aNumber;
    if(diff >0)
       return 2;
    return 0;
}
