#ifndef SHARED_XML_COURSE_CREATE_UTIL_H
#define SHARED_XML_COURSE_CREATE_UTIL_H

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include "../global.h"

#include "shared_cs_util.h"
#include "shared_util.h"
#include "shared_roster_xml_parser.h"
#include "shared_survey_string.h"
#include "shared_authenticate.h"
#include "shared_central_user.h"
#include "shared_file_util.h"
#include "shared_server_string.h"
#include "shared_encrypt.h"
#include "shared_user_index.h"
#include "shared_super_util.h"
#include "shared_strtrm.h"
#include "shared_new_course_lock.h"
#include "shared_add_util.h"
#include "shared_authenticate.h"
#include "shared_lock.h"
#include "shared_super_util.h"
#include "shared_person_list.h"
#include "shared_time.h"
#include "shared_course_info.h"
#include "shared_update_user_info.h"
#include "shared_wnec_roster_log.h"
#include "shared_system_data.h"

HDF *hdf;

extern int global_new_central_user_count;


/* The administrator is given a chance to alter the following data items found in the XML
** file before the course is created.
**
** The name of the directory where the course is stored (the 'internal course name')
** The name of the subdirectory (under the standard 'courses' directory) where the course will
** be stored.
** 
** This data structure keeps track of these data items for each course created.
*/

typedef struct directory_name_node
   {
     char name[MAX_COURSE_NO +1];             /* the original internal name of the course, as stored in the XML file */
     char dir_id[MAX_COURSE_ID +1];           /* the new internal name of the course, as modified by the user */
     char subdir[MAX_COURSE_SUBDIR + 1];      /* the original internal subdirectory for the course */
     char modified_subdir[MAX_COURSE_SUBDIR + 1];      /* the new internal subdirectory for the course */
     COURSE_TYPE course_type;                 /* Standalone, Normal or Template */
     struct directory_name_node *next;
   } DIRECTORY_NAME_NODE;



typedef enum user_state{NEW,           /* this is a new user */
                        NEW_1, 
                        EXISTS,        /* this is an existing user */
                        ERROR_UID,     /* couldn't derive a username */
                        ERROR_NAME     /* name in xml file didn't match existing name */
                        }USER_STATE;
                        
typedef enum user_add_state{FINISH,    /* user was successfully added */
                            FAILED,    /* error occurred while creating user */
                            USEREXISTS /* user was already in the course */
                            }USER_ADD_STATE;
                            

typedef enum user_central_state{C_ERROR, /* an error occurred while adding user to central database */
                                SUCCESS,  /* user was successfully added to central database */
                                UN_CHANGE /* user was already in database, no changes required */
                                }USER_CENTRAL_STATE;

typedef struct user 
{
    char first[MAX_NAME +1];
    char last[MAX_NAME +1];
    char id[MAX_ID +1];
    char username[MAX_USERNAME +1];
    char password[MAX_PASSWORD +1];
    GROUP_TYPE group;
    USER_STATE is_new;
    USER_ADD_STATE add_state;
    USER_CENTRAL_STATE central_state;
}USER;

typedef struct user_node
{
     USER user;
     struct user_node *next;
}USER_NODE;

typedef enum course_state{UPDATE,      /* course already existed, this is an update */
                          C_NEW,       /* this is a completely new course */
                          DIR_ERR,     /* couldn't create course directory */
                          MSG_ERR,     /* couldn't create chat message file */
                          CONFIG_ERR,  /* couldn't write config.dat */
                          COURSE_ERR,   /* general error? */
                          TYPE_CONFLICT  /* course type conflict */
                          }  COURSE_STATE;
                          
/* adding teacher to a course */                          
typedef enum t_pass_state{OPEN_ERR,   /* error appending to password file */ 
                          T_SUCCESS   /* all teachers added successfully */
                          }T_PASS_STATE;



typedef struct master_course_list
  {
    char course_subdir[MAX_COURSE_SUBDIR + 1];
    char course_dir[MAX_COURSE_ID + 1];
    char org_id[MAX_COURSE_ID + 1];
    char course_path[MAX_PATH + 1];
    char course_no[MAX_COURSE_NO + 1];
    char course_title[MAX_COURSE_TITLE + 1];
    char course_semester[MAX_SEMESTER + 1];
    char instructor_title[MAX_INSTRUCTOR + 1];
  
    COURSE_TYPE course_type;
    COURSE_STATE exists; 
    T_PASS_STATE t_state; 
  
    USER_NODE *head;       /* list of teachers only */
    USER_NODE *add_head;   /* complete list of people who have been added to the course */
    USER_NODE *add_current;
  
    struct master_course_list *next;
  }  CREATED_COURSE_NODE;



typedef struct course_group
{
     char course_subdir[MAX_COURSE_SUBDIR + 1];
     char course_dir[MAX_COURSE_NO +1];
     COURSE_TYPE course_type;
     GROUP_TYPE group;
     struct course_group *next;
}COURSE_GROUP;

typedef struct user_group_info
{
    USER user;
    COURSE_GROUP *head;
    COURSE_GROUP *current;
    struct user_group_info *next;
}USER_GROUP_INFO;

typedef struct user_group_info_list
{
    USER_GROUP_INFO *head;
    USER_GROUP_INFO *current;
}USER_GROUP_INFO_LIST;





       
USER_GROUP_INFO_LIST *build_user_list(XML_COURSE_INFO_LIST *list);

CREATED_COURSE_NODE* build_normal_template_course_list(XML_COURSE_INFO_LIST *list);

CREATED_COURSE_NODE *standalone_course_list(XML_COURSE_INFO_LIST *list);

void set_course_table(CREATED_COURSE_NODE *head, const char *prefix);

DIRECTORY_NAME_NODE *get_parameters(char *key, int *standalone, char *roster_path);

void free_directory_name_list(DIRECTORY_NAME_NODE *head);


void check_internal_course_names(XML_COURSE_INFO_LIST *list);

XML_COURSE_INFO_LIST *parse_xml_file(const char *xml_file_path);

void update_xml_info_list(XML_COURSE_INFO_LIST *list, DIRECTORY_NAME_NODE *modified_head);

void free_teacher_node(USER_NODE *t_head);

void free_course_f_list(CREATED_COURSE_NODE *head);

void free_user_group_info_list(USER_GROUP_INFO_LIST *list);

INDEX_USER_LIST *derive_teacher_username_password(CREATED_COURSE_NODE *course_head, INDEX_USER_LIST *index_list);

INDEX_USER_LIST * derive_student_username_password(USER_GROUP_INFO_LIST *user_list,INDEX_USER_LIST *index_list);

CREATED_COURSE_NODE *add_user_to_course_list(CREATED_COURSE_NODE *course, USER *ptr);

CREATED_COURSE_NODE *add_students_to_courses(CREATED_COURSE_NODE *course_head,USER_GROUP_INFO_LIST *user_list);

CREATED_COURSE_NODE * write_students_to_password_file(CREATED_COURSE_NODE *courses);

CREATED_COURSE_NODE *create_course_with_teachers(CREATED_COURSE_NODE *course_head);

void create_standalone_with_students(CREATED_COURSE_NODE *stand_head); 
 void
update_standalone_username(CREATED_COURSE_NODE *sta_list);
INDEX_USER_LIST *process_one_username(USER *ptr, INDEX_USER_LIST *index_list);
void write_add_drop_list(CREATED_COURSE_NODE *courses);
void
set_course_data_record_log(CREATED_COURSE_NODE *head, const char *prefix, const char *action);

void check_invalid_chars(const char *string);
#endif
