#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <time.h>

#include <ClearSilver.h>
#include <sqlite3.h>
#include "global.h"
#include "grade.h"		/* for date FORMAT strings */
#include "manhat-lib/shared_util.h"
#include "manhat-lib/shared_grade_book_menu.h"
#include "manhat-lib/shared_file_util.h"
#include "manhat-lib/shared_grade_book_util.h"
#include "manhat-lib/shared_grade_book_db.h"
#include "manhat-lib/shared_person_list.h"
#include "manhat-lib/shared_grade_book_calculation_util.h"
#include "manhat-lib/shared_grade_book_create_db.h"

void
read_parameters ( char *course, char *key)
{
     cs_get_required_parameter("crs", course, MAX_PATH);
     cs_get_required_parameter("id", key, MAX_KEY);

}


int create_database(CONFIG_STRUCT *conf)
{
    char name[MAX_PATH +1];
    int dummy;
    snprintf(name, MAX_PATH +1, "%s%s", conf->course_path, GRADE_BOOK_DIR);
    if(!file_exists(name))
        mkdir(name, 0775);

    snprintf(name, MAX_PATH +1, "%s%s/%s", conf->course_path, GRADE_BOOK_DIR, GRADE_BOOK_DB);
    if(!file_exists(name))
        return create_db_tables(conf, &dummy);
    return 1;
}

void get_all_grades(CONFIG_STRUCT *conf, P_NODE *head)	
{
    if(global_item_list && global_item_list->head)
    {
	for(global_item_list->current = global_item_list->head; global_item_list->current; global_item_list->current = global_item_list->current->next)
	{
	   if(strcmp(global_item_list->current->grade_entered, "yes") ==0)
	   {
	
	       get_one_item_grade_list(conf, global_item_list->current->item_id, GRADE_BOOK_DB); /* shared_grade_book_db.h */
	       if(global_grade_temp_list && global_grade_temp_list->head)
	       {
		  
		   if(strcmp(global_item_list->current->is_letter_grade, "yes") == 0)
			 update_letter_log_list(conf,  global_item_list->current->item_id, GRADE_BOOK_DB, global_grade_temp_list);  /* shared_grade_book_db.h */
                       
                       mark_deleted_students(global_grade_temp_list, head);
	               global_item_list->current->grades = global_grade_temp_list;
	       }

	   }
	}
    }
}

void set_all_item_grades()
{
#define MAX_TMP 50
    GRADE *ptr;
    ITEM *item_ptr;
    char name[MAX_TMP];
    char temp[MAX_TMP];


    for(item_ptr = global_item_list->head; item_ptr; item_ptr = item_ptr->next)
    {
	 if(item_ptr->grades)
	 {
            for(ptr = item_ptr->grades->head; ptr; ptr = ptr->next)
	    {
	       if(strcmp(item_ptr->is_letter_grade, "no") == 0)
	       {
	          snprintf(name, MAX_TMP, "score.%s.%d.score", ptr->username, ptr->item_id);
	          snprintf(temp, MAX_TMP, "%4.*f", test_precision(ptr->score), ptr->score);
                  cs_set_value(name, temp);
	       } 
	       else
	       {
	          snprintf(name, MAX_TMP, "score.%s.%d.letter", ptr->username, ptr->item_id);
                  cs_set_value(name, ptr->letter);
	       }
	      snprintf(name, MAX_TMP, "score.%s.%d.excuse", ptr->username, ptr->item_id);
              cs_set_value(name, ptr->excuse);
	      snprintf(name, MAX_TMP, "score.%s.%d.pending", ptr->username, ptr->item_id);
              cs_set_value(name, ptr->pending);
	      snprintf(name, MAX_TMP, "score.%s.%d.item_id", ptr->username, ptr->item_id);
              cs_set_int_value(name, ptr->item_id);
	      snprintf(name, MAX_TMP, "score.%s.%d.drop", ptr->username, ptr->item_id);
              cs_set_value(name, ptr->drop);
               
            }
	     
	 }
    }

 #undef MAX_TMP 
}

void set_std_total_grade(TOTAL_GRADE *std_grade)
{
   #define MAX_TMP 50
   TOTAL_GRADE *ptr;
   char name[MAX_TMP];
   char temp[MAX_TMP];
   double total =0;
   double max =-1;
   double min =999999;
   double avg =0;
   char letter[MAX_GRADE_LEN +1];
   int count =0;

    for(ptr = std_grade; ptr; ptr = ptr->next)
    {
       
	if(ptr->total >=0)
	{

          snprintf(name, MAX_TMP, "score.%s.total", ptr->username);
          snprintf(temp, MAX_TMP, "%4.*f", test_precision(ptr->total), ptr->total);
	  cs_set_value(name, temp);
          snprintf(name, MAX_TMP, "score.%s.grade", ptr->username);
	  cs_set_value(name, ptr->grade);
	  total += ptr->total;
	  if(max < ptr->total)
              max = ptr->total;
	  if(min > ptr->total)
	     min = ptr->total;
        count++;
	}
	
    }

  if(count >0 && total > MIN_GRADE_BOOK)
  {
   avg = total/(float)count; 

   snprintf(temp, MAX_TMP, "%4.2f", global_grade_conf.rounding_method == WHOLE_NUMBER ? whole_number(avg): nearest_tenth(avg));
   cs_set_value("avg", temp);

   snprintf(temp, MAX_TMP, "%4.2f", global_grade_conf.rounding_method == WHOLE_NUMBER ? whole_number(min): nearest_tenth(min));
   cs_set_value("min", temp);
   
   snprintf(temp, MAX_TMP, "%4.2f", global_grade_conf.rounding_method == WHOLE_NUMBER ? whole_number(max): nearest_tenth(max));
   cs_set_value("max", temp);
   
   get_one_student_grade(global_grade_conf.rounding_method == WHOLE_NUMBER ? whole_number(min): nearest_tenth(min), letter);
   cs_set_value("min_grade", letter);

   get_one_student_grade(global_grade_conf.rounding_method == WHOLE_NUMBER ? whole_number(max): nearest_tenth(max), letter);
   cs_set_value("max_grade", letter);

   get_one_student_grade(global_grade_conf.rounding_method == WHOLE_NUMBER ? whole_number(avg): nearest_tenth(avg), letter);
   cs_set_value("avg_grade", letter);
  } 
 #undef MAX_TMP 
}



void  do_action(CONFIG_STRUCT *conf, SESSION *user)
{
    P_NODE *head;
    TOTAL_GRADE *std_grade =0;

    head = build_option_person_list (conf);  /* shared_person_list.c */
    set_person_list_values(head, user);   /* shared_grade_book_util.c */

    get_categories(conf, GRADE_BOOK_DB);  /* shared_grade_book_db.h */



    if(global_cat_list && global_cat_list->head)
    {
	set_cat_list_values();               /* shared_grade_book_util.h */
        get_items(conf, GRADE_BOOK_DB, 0);     /* shared_grade_book_db.h */
	if(global_item_list && global_item_list->head)
	{
           get_all_grades(conf, head);	

	   get_items_min_avg_max(conf, GRADE_BOOK_DB);   /* shared_grade_book_calculation_util.h */

           set_all_item_grades();
	   set_item_list_values(1, 0);        /* shared_grade_book_util.h */
	   std_grade = calculate_total_grades(head, conf, GRADE_BOOK_DB); /* shared_grade_book_calculation_util.h */
	   if(std_grade)
	   {
	        set_std_total_grade(std_grade);
		free_total_grade_list(std_grade);
                cs_set_int_value("max_min_avg", 1);
                cs_set_int_value("view_bar", 1);
                cs_set_int_value("view_total", 1);
	   }
         

	}

    }


    if(head)
	free_option_person_list(head);    /* shared_person_list.c */
    if(global_cat_list)
	free_category_list(global_cat_list);
    if(global_item_list)
	free_item_list(global_item_list);
    if(global_scale_list)
       free_scale_list(global_scale_list);

}




int
main ()
{
  char course[MAX_PATH +1];
  char key[MAX_KEY +1];
  char *print = 0;

  SESSION user;
  CONFIG_STRUCT conf;
  
  cs_cgi_init();   /* shared_cs_util.h */
  read_parameters ( course, key);
  read_configuration_file (course, &conf);	
  validate_key (key, &user, &conf);	
  cs_set_course_info(&conf);  
  set_grade_book_menu("grade_book", key, course); /* shared_grade_book_menu.h */
  cs_load_lang("grade_book_menu_util");


  if(user.group != FACULTY)
	 cs_critical_error(ERR_REQUEST_DENIED, "grade_book");

  if(!create_database(&conf))
	 cs_critical_error(ERR_GRADES_DB, "grade_book");
 
  print = hdf_get_value(global_cgi->hdf, "Query.print", "");

  do_action(&conf, &user);

  cs_set_int_value("MIN_GRADE_BOOK", MIN_GRADE_BOOK);
  
  cs_load_lang("grade_book");
  if(strlen(print) >0 && strcmp(print, "yes") ==0)
     cs_cgi_display ("grade_book_print", 0);
  else
     cs_cgi_display ("grade_book", 0);
  cs_cgi_destroy();      

  return 0;			

}


