#include "manhat-lib/shared_xml_course_create_util.h"
#include "manhat-lib/shared_course_request_xml.h"

void dump_xml_list(XML_COURSE_INFO_LIST *list);
void dump_user_list(USER_GROUP_INFO_LIST *user_list);

    
static void
set_course_data(CREATED_COURSE_NODE *head, const char *prefix)
{
#define MAX_TMP_NAME 50
       	
   CREATED_COURSE_NODE *ptr;
   USER_NODE *t_node;
   int course_count =0;
   int people_count, i =0;
   char name[MAX_TMP_NAME];

   for(ptr = head; ptr; ptr = ptr->next)
   {
	  snprintf(name, MAX_TMP_NAME, "%s.%d.type", prefix, i);
	  cs_set_int_value(name, ptr->course_type);
    
	  snprintf(name, MAX_TMP_NAME, "%s.%d.course_subdir", prefix , i);
	  cs_set_value(name, ptr->course_subdir);
	  snprintf(name, MAX_TMP_NAME, "%s.%d.course_dir", prefix , i);
	  cs_set_value(name, ptr->course_dir);
	  snprintf(name, MAX_TMP_NAME, "%s.%d.course_org", prefix , i);
	  cs_set_value(name, ptr->org_id);
	  snprintf(name, MAX_TMP_NAME, "%s.%d.course_no", prefix , i);
	  cs_set_value(name, ptr->course_no);
	  snprintf(name, MAX_TMP_NAME, "%s.%d.course_title", prefix , i);
	  cs_set_value(name, ptr->course_title);
	  snprintf(name, MAX_TMP_NAME, "%s.%d.course_semester", prefix , i);
	  cs_set_value(name, ptr->course_semester);
	  snprintf(name, MAX_TMP_NAME, "%s.%d.exists", prefix , i);
	  cs_set_int_value(name, ptr->exists);
      
          course_count++;
          people_count =0; 
      for(t_node = ptr->add_head; t_node; t_node = t_node->next)
      {
	  if(strcmp(t_node->user.password, "add") == 0)
	  {
	     snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.first", prefix , i, people_count);
	     cs_set_value(name, t_node->user.first);
	     snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.last", prefix , i, people_count);
	    cs_set_value(name, t_node->user.last);
	    snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.id", prefix , i, people_count);
	    cs_set_value(name, t_node->user.id);
	    snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.username", prefix , i, people_count);
	    cs_set_value(name, t_node->user.username);
	    snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.group", prefix , i, people_count);
	    if(t_node->user.group == FACULTY)
	       cs_set_value(name, "faculty");
	    else
	       cs_set_value(name, "student");

	    snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.add_state", prefix , i, people_count);
	    if(t_node->user.add_state == FINISH)
	       cs_set_value(name, "added successfully to class,");
	    else if(t_node->user.add_state == USEREXISTS)
	       cs_set_value(name, "existed user (deleted for some reason, now added success)");
	    else
	       cs_set_value(name, "failed to add to class,");

	    snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.central_state", prefix , i, people_count);
	    if(t_node->user.central_state == SUCCESS)
	     cs_set_value(name, "central add success");
	    else if(t_node->user.central_state == C_ERROR)
	     cs_set_value(name, "central add error");
	    else
	     cs_set_value(name, "central unchange");

           people_count++ ; 
	  }

      }
     i++;
   }
   if(!strcmp(prefix, "ctr"))   
    cs_set_int_value("ctr_total", course_count); 
#undef MAX_TMP_NAME 
} 
    




void    
read_parameters( char *roster_path)
{
    char *address = 0;

    address = hdf_get_value(global_cgi->hdf, "CGI.RemoteAddress", 0);
    if(!address)
	cs_critical_error(ERR_REQUEST_DENIED, " update course");
    if(strcmp(address, "127.0.0.1"))
	cs_critical_error(ERR_REQUEST_DENIED, " update course");
    
    cs_get_required_parameter ("roster_path", roster_path, MAX_PATH);
}

P_NODE * get_one_user_node(P_NODE *users)
{
     P_NODE *new_node;

     new_node = (P_NODE*)malloc(sizeof(P_NODE));
     if(!new_node)
	 cs_critical_error(ERR_MALLOC_FAILED, "get_one_user_node");

     strncpy(new_node->data.realname, users->data.realname, MAX_NAME +1);
     strncpy(new_node->data.lastname, users->data.lastname, MAX_NAME +1);
     strncpy(new_node->data.id, users->data.id, MAX_ID +1);
     if(strlen(users->data.username))
        strncpy(new_node->data.username, users->data.username, MAX_USERNAME +1);
     else
	new_node->data.username[0] = '\0';
     new_node->data.group = users->data.group;
     new_node->next = 0;

    return new_node;

}

XML_COURSE_INFO* get_course_info_node(XML_COURSE_INFO *one_course, const char *manhat_id, COURSE_TYPE type)
{
    XML_COURSE_INFO *ptr;
    P_NODE *users, *user_ptr;

     ptr = (XML_COURSE_INFO*)malloc(sizeof(XML_COURSE_INFO));
     if(!ptr)
	  cs_critical_error(ERR_MALLOC_FAILED, "get_course_info_node");

     strncpy(ptr->subdir, one_course->subdir, MAX_COURSE_SUBDIR +1); 
     strncpy(ptr->dir_id, one_course->dir_id, MAX_COURSE_ID +1); 
     strncpy(ptr->real_dir_id, manhat_id, MAX_COURSE_ID +1); 
     strncpy(ptr->semester, one_course->semester, MAX_SEMESTER +1); 
     strncpy(ptr->course_code, one_course->course_code, MAX_COURSE_NO +1); 
     strncpy(ptr->title, one_course->title, MAX_COURSE_TITLE +1); 
     if(strlen(one_course->instructor_title))
        strncpy(ptr->instructor_title, one_course->instructor_title, MAX_INSTRUCTOR +1); 
     else
	ptr->instructor_title[0] = '\0';
     ptr->course_type = type;
     ptr->next = 0;

     ptr->user_head = 0;
     ptr->user_current = 0;

     for(users = one_course->user_head; users; users = users->next)
     {
           user_ptr = get_one_user_node(users);
	   if(!ptr->user_head)
		 ptr->user_head = user_ptr;
	   else
		 ptr->user_current->next = user_ptr;
	   ptr->user_current = user_ptr;
		 
     }
     return ptr;
}








static XML_COURSE_INFO_LIST * 
get_existing_course_list(XML_COURSE_INFO_LIST *list, SUBDIR_COURSE_LIST *sub_list)
{
    XML_COURSE_INFO_LIST *exist_list =0;
    XML_COURSE_INFO *ptr;
    int found =0;
    COURSE_TYPE type;
    char manhat_course_id[MAX_COURSE_ID +1];
    
    if(sub_list)
    {
	
        exist_list = (XML_COURSE_INFO_LIST *)malloc(sizeof(XML_COURSE_INFO_LIST));
        exist_list->head = 0;
	exist_list->current = 0;

	for(list->current=list->head; list->current; list->current=list->current->next)
	{
	  found = find_manhat_course_id(sub_list,
	         list->current->subdir,list->current->dir_id,manhat_course_id, &type);
	  if(found)
	  {
             ptr = get_course_info_node(list->current, manhat_course_id, type);

             if(!exist_list->head)
		    exist_list->head = ptr;
	     else
		    exist_list->current->next = ptr;
	     exist_list->current = ptr;
	        
	  }
	}
    }
    return exist_list;
} 

void update_existing_courses(CREATED_COURSE_NODE *course_head)
{
   CREATED_COURSE_NODE *ptr;
   for(ptr = course_head; ptr; ptr = ptr->next)
   {
       ptr->exists = UPDATE;
       ptr->t_state = T_SUCCESS;     
       snprintf(ptr->course_path, MAX_PATH +1, "%s%s/%s",
                          COURSE_PATH, ptr->course_subdir, ptr->course_dir);

   }
}	


void get_division(const char *roster_path, char *division)
{
    char divs[4][20] = {"Day_and_evening_", "Off_campus_", "Law_school_", "11_week_"};
    char divisions[4][20] = {"Day and evening", "Off campus", "Law school", "11 week"};
    int i;
    char *ptr;

    for(i =0; i<4; i++)
    {
        ptr = strstr(roster_path, divs[i]);
        if(ptr)
	{
	    strncpy(division, divisions[i], MAX_PATH +1);
	    break; 
	}	
    }
}

int check_request_file_exists(const char *roster_path, char *file)
{
     char division[MAX_PATH +1];

     get_division(roster_path, division);
     get_request_list_filename(division, file);  /* shared_course_request_xml.h */
     if(file_exists(file))
      {
	  return 1;
      }
     return 0;
}

XML_COURSE_INFO *
find_course_in_xml_info_list(XML_COURSE_INFO_LIST *xml_info_list, REQUEST_COURSE *one)
{
     for(xml_info_list->current = xml_info_list->head;
         xml_info_list->current;
         xml_info_list->current = xml_info_list->current->next)
     {
	 if( !strcmp(xml_info_list->current->subdir,one->subdir) &&
	     !strcmp(xml_info_list->current->dir_id, one->sis_id))
		 return xml_info_list->current;
     }
     return 0;
}


XML_COURSE_INFO_LIST *
  add_to_existing_list(XML_COURSE_INFO_LIST *existing_course_list, XML_COURSE_INFO *one_course)
{
	XML_COURSE_INFO *ptr;
	int flag = 0;

       if(!existing_course_list)
       {
	 existing_course_list = (XML_COURSE_INFO_LIST *)malloc(sizeof(XML_COURSE_INFO_LIST));
	 if(!existing_course_list)
		cs_critical_error(ERR_MALLOC_FAILED, "");
	 existing_course_list->head = 0;
	 existing_course_list->current = 0;
	 existing_course_list->head = get_course_info_node(one_course, one_course->dir_id, CENTRAL);
         existing_course_list->current = existing_course_list->head;
       }
       else
       {
	  if(!existing_course_list->head)
	  {
	 existing_course_list->head = get_course_info_node(one_course, one_course->dir_id, CENTRAL);
         existing_course_list->current = existing_course_list->head;
	  }
	  else
	  {
	    for(ptr = existing_course_list->head; ptr; ptr = ptr->next)
	    {
	      if( !strcmp(ptr->subdir, one_course->subdir) &&    
		  !strcmp(ptr->dir_id, one_course->dir_id))
	      {
		 flag = 1;
		 break;
	      }
	   }
	    if(!flag)
	    {
             existing_course_list->current = existing_course_list->head;
	     while(existing_course_list->current->next)
	     {
                existing_course_list->current = existing_course_list->current->next;
	     }
             existing_course_list->current->next = get_course_info_node(one_course, one_course->dir_id, CENTRAL);
	  }
        }
       }
       return existing_course_list;
}


XML_COURSE_INFO_LIST *                                  
 add_request_course_list(XML_COURSE_INFO_LIST *xml_info_list, 
		         XML_COURSE_INFO_LIST *existing_course_list, 
			 REQUEST_COURSE_LIST *list)
{
     XML_COURSE_INFO *found = 0;
    
     for(list->current = list->head; list->current; list->current = list->current->next)
     {
         found = find_course_in_xml_info_list(xml_info_list, list->current);
	 if(found)
	  {
	     existing_course_list = add_to_existing_list(existing_course_list, found);
	  }   
     }
     
     return existing_course_list;
}	



int main()
{
   
   XML_COURSE_INFO_LIST *xml_info_list;                                  /* shared_roster_xml_parser.h */
   XML_COURSE_INFO_LIST *existing_course_list =0;                                  /* shared_roster_xml_parser.h */
   CREATED_COURSE_NODE *course_head = 0;
   USER_GROUP_INFO_LIST *user_list = 0;
   INDEX_USER_LIST *index_list = 0;
   SUB_DIR_ID_NODE *unique_dir_list;
   SUBDIR_COURSE_LIST *sub_list;
   REQUEST_COURSE_LIST *request_list;

   
   char roster_path[MAX_PATH + 1];   /* full (relative) path to xml file */ 
   char file[MAX_PATH + 1];   
  
   cs_cgi_init(); 
   

   /* build a linked list of directory names assigned to each course by the user */
   read_parameters( roster_path);
  
   /* parse the xml file into a linked list */
   xml_info_list = parse_xml_file(roster_path);   /* parse xml file */

   unique_dir_list = build_unique_subdir_list(xml_info_list);  /* shared_course_info.c */
   sub_list = build_sub_list_info(unique_dir_list);            /* shared_course_info.c */
   free_sub_list_info(unique_dir_list);                        /* shared_course_info.c */

   if(sub_list)
      existing_course_list = get_existing_course_list(xml_info_list, sub_list);     

   if(check_request_file_exists(roster_path, file))
   {

      request_list = xml_request_course_parser(file);   /* shared_course_request_xml.c */
      if(request_list->head)
      {

         existing_course_list = add_request_course_list(xml_info_list, existing_course_list, request_list);

      }

      free_request_list( request_list);           /* shared_course_request_xml.c */ 
   }

   free_xml_data_list(xml_info_list);


   if(!existing_course_list)
       cs_critical_error(ERR_GENERAL_ERROR, "NO courses were found that were automatically created from a SIS roster.");

   if(!existing_course_list->head)
   {
       free(existing_course_list);
       cs_critical_error(ERR_GENERAL_ERROR, "NO courses were found that were automatically created from a SIS roster.");
   }
  
   

   /* only one admin can create a course at a time */
   get_new_course_lock();    /* shared_new_course_lock.c */
   
   

   /* start list with normal and template courses
   ** and only teacher info 
   */
   course_head = build_normal_template_course_list(existing_course_list);  /* shared_xml_course_create_util.c */ 
   //update_existing_courses(course_head);                             
   
 
   if(course_head)
   {
      index_list = (INDEX_USER_LIST *)malloc(sizeof(INDEX_USER_LIST));   
      index_list->current =0;
      index_list->head =0;

      index_list = build_index_user_list(index_list);     /* shared_user_index.c */
      index_list = derive_teacher_username_password(course_head,index_list); /*shared_xml_course_create_util.c */

      course_head =create_course_with_teachers(course_head);   /* shared_xml_course_create_util.c */

      user_list = build_user_list(existing_course_list);    /* list contains all students, with their courses */


      if(user_list)
       {
          index_list=derive_student_username_password(user_list,index_list);  /* shared_xml_course_create_util.c */
          course_head = add_students_to_courses(course_head, user_list);      /* shared_xml_course_create_util.c */
          write_students_to_password_file(course_head);                       /* shared_xml_course_create_util.c */
          reindex_users("../users");     /* shared_user_index.c */
          set_course_data(course_head, "ctr");                                /* shared_xml_course_create_util.c */
	  write_add_drop_list(course_head);                                   /* shared_xml_course_create_util.c */
      } 
   }


   free_xml_data_list(existing_course_list);
   if(index_list)
     free_index_user_list(index_list);     /* shared_user_index.c */
   if(course_head)
     free_course_f_list(course_head);      /* shared_xml_course_create_util.c */
   if(user_list)
     free_user_group_info_list(user_list); /* shared_xml_course_create_util.c */
   free_subdir_course_list(sub_list);

   free_new_course_lock();   /* shared_new_course_lock.c */  
   cs_cgi_display("super_update_courses", 0);
   cs_cgi_destroy(); 
   return 0;
}
    



	       
