#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>		/* for unlink() */
#include <ctype.h>
#include <sys/types.h>
#include <dirent.h>
       
#include "../global.h"

#include "shared_lock.h"
#include "shared_util.h"
#include "shared_strtrm.h"
#include "shared_news_util.h"
#include "shared_authenticate.h"
#include "shared_update_user_info.h"   /* for mark_passwd_file() */
#include "shared_file_util.h"
#include "shared_cs_util.h"


#include "shared_delete.h"



static
COURSE_NODE *
exclude_deleted_course_list(char *username, char *crs)
{
    COURSE_NODE *ptr, *current = 0, *head = 0;
    char course_path[MAX_PATH + 1];
    char line[MAX_LINE + 1];
    FILE *fp;
    char dir;

    dir = sub_dir_name(username);   /* shared_authenticate.c */
    snprintf(course_path, MAX_PATH, "../%s/%c/%s/%s", USERS_DIR, dir, username,  COURSE_LIST_FNAME);
    fp = fopen(course_path, "r");
    if(!fp)
      cs_critical_error (ERR_FREAD_FAILED, "");
    get_shared_lock(fileno(fp), 1);
    while(fgets (line, MAX_LINE, fp))
    {
        strtrm(line);  /* shared_strtrm.c */
        if(strcmp(line, crs) != 0)
        {
           ptr = (COURSE_NODE *)malloc(sizeof(COURSE_NODE));
           strncpy(ptr->crs, line, MAX_PATH);
           ptr->next = 0;
           if(!head)
           {
               head = ptr;
           }
           else
               current->next = ptr;
           current = ptr;
       }
    }

    release_lock(fileno(fp));
    fclose(fp);
    return head;

}

/** re-writes the list of courses username is enrolled in
***/

static void
rewrite_course_list(COURSE_NODE *head,  char *username)
{
    FILE *fp;
    char course_path[MAX_PATH +1];
    COURSE_NODE *ptr;
    char dir;
  
    dir = sub_dir_name(username);
    snprintf(course_path, MAX_PATH + 1, "../%s/%c/%s/%s", USERS_DIR, dir, username,  COURSE_LIST_FNAME);
    fp = fopen(course_path, "w");
    if(!fp)
      cs_critical_error (ERR_FOPEN_WRITE_FAILED, "");
    get_exclusive_lock(fileno(fp), 1);
    for(ptr = head; ptr; ptr = ptr->next)
      fprintf(fp, "%s\n", ptr->crs);
    release_lock(fileno(fp));
    fclose(fp);
}


/* deletes this users key associated with this course */
static void 
delete_course_session_key(const char *username, const char *crs)
{
   char key_path[MAX_PATH +1];
   
   /* sub_dir_name() is in shared_authenticate.c */
    snprintf(key_path, MAX_PATH + 1, "../%s/%c/%s/%s%s", USERS_DIR, sub_dir_name(username), username,  
                                         crs, KEY_FILE_EXTENSION);   
    unlink(key_path);
}                                          
   

void
free_course_list(COURSE_NODE *head)
{
   COURSE_NODE *ptr;
   while (head)
    {
      ptr = head->next;
      free (head);
      head = ptr;
    }
}






void
delete_course(char *username, char *crs)
{
    COURSE_NODE *head;

    head = exclude_deleted_course_list(username, crs);
    rewrite_course_list(head, username);
    free_course_list(head);
    delete_course_session_key(username, crs);
}


/* returns 1 if directory dirname contains a file that starts with inf_, else 0 */
static int
contains_inf_file (const char *dirname)
{
  DIR *dir_p;
  struct dirent *dir_entry_p;
  char *ptr;


  dir_p = opendir (dirname);
  if (!dir_p)
      return 0;


  while (NULL != (dir_entry_p = readdir (dir_p)))
    {
      ptr = strstr (dir_entry_p->d_name, "inf_");
      if (ptr && (ptr == dir_entry_p->d_name))	/* i.e. if file starts with inf_ */
	{
	  closedir (dir_p);
	  return 1;
	}
    }
  closedir (dir_p);
  return 0;
}



/* returns 1 if directory dirname contains a file that ENDS with .inf else 0 
** In the Post Office, info file end with *.inf, while in the rest of Manhattan
** info files start with inf_.
**
** This function needs to be changed after mktemp() is removed from post office
** routines
*/
static int 
contains_postoffice_inf_file (const char *dirname)
{
  DIR *dir_p;
  struct dirent *dir_entry_p;
  char *ptr;


  dir_p = opendir (dirname);
  if (!dir_p)
    cs_critical_error (ERR_OPENDIR_FAILED, "");


  while (NULL != (dir_entry_p = readdir (dir_p)))
    {
      ptr = strstr (dir_entry_p->d_name, ".inf");
      if (ptr && (strlen(ptr) == 4))	/* i.e. if file ends with .inf */
	{
	  closedir (dir_p);
	  return 1;
	}
    }
  closedir (dir_p);
  return 0;
}


/* returns 1 if one of username's dirs contains an *.inf file, else 0
**/
int
user_contributed (const char *username, CONFIG_STRUCT *conf)
{
  char dirname[MAX_PATH + 1];


  snprintf (dirname, MAX_PATH + 1, "%s%s/%s/%s",
	    conf->course_path, PEOPLE_DIR,  username, ASSIGNMENTS_DIR);
  if (contains_inf_file (dirname))
    return 1;


  snprintf (dirname, MAX_PATH + 1, "%s%s/%s/%s",
	    conf->course_path, PEOPLE_DIR,  username, ANONYMOUS_DIR);
  if (contains_inf_file (dirname))
    return 1;


  snprintf (dirname, MAX_PATH + 1, "%s%s/%s/%s",
	    conf->course_path, PEOPLE_DIR,  username, DISCUSSION_DIR);
  if (contains_inf_file (dirname))
    return 1;


  snprintf (dirname, MAX_PATH + 1, "%s%s/%s/%s",
	    conf->course_path, PEOPLE_DIR,  username, TEAM_DIR);
  if (contains_inf_file (dirname))
    return 1;


  snprintf (dirname, MAX_PATH + 1, "%s%s/%s/%s",
	    conf->course_path, PEOPLE_DIR,  username, INET_DIR);
  if (contains_inf_file (dirname))
    return 1;
    

  snprintf (dirname, MAX_PATH + 1, "%s%s/%s/%s",
	    conf->course_path, PEOPLE_DIR,  username, LOUNGE_DIR);
  if (contains_inf_file (dirname))
    return 1;

  snprintf (dirname, MAX_PATH + 1, "%s%s/%s/%s",
	    conf->course_path, PEOPLE_DIR,  username, MAIL_DIR);
  if (contains_postoffice_inf_file (dirname))
    return 1;

  snprintf (dirname, MAX_PATH + 1, "%s%s/%s/%s",
	    conf->course_path, PEOPLE_DIR,  username, HANDOUTS_DIR);
  if (contains_inf_file (dirname))
    return 1;


  snprintf (dirname, MAX_PATH + 1, "%s%s/%s/%s",
	    conf->course_path, PEOPLE_DIR,  username, LECTURES_DIR);
  if (contains_inf_file (dirname))
    return 1;


  snprintf (dirname, MAX_PATH + 1, "%s%s/%s/%s",
	    conf->course_path, PEOPLE_DIR,  username, GRADES_DIR);
  if (contains_inf_file (dirname))
    return 1;




  snprintf (dirname, MAX_PATH + 1, "%s%s/%s/%s",
	    conf->course_path, PEOPLE_DIR,  username, TEAM_TEACH_DIR);
  if (contains_inf_file (dirname))
    return 1;

  snprintf (dirname, MAX_PATH + 1, "%s%s/%s/%s",
	    conf->course_path, PEOPLE_DIR,  username, SURVEYS_DIR);
  if (contains_inf_file (dirname))
    return 1;


  snprintf (dirname, MAX_PATH + 1, "%s%s/%s/%s",
	    conf->course_path, PEOPLE_DIR,  username, SELFTEST_DIR);
  if (contains_inf_file (dirname))
    return 1;

  snprintf (dirname, MAX_PATH + 1, "%s%s/%s/%s",
	    conf->course_path, PEOPLE_DIR,  username, PODCASTS_DIR);
  if (contains_inf_file (dirname))
    return 1;



  return 0;
}




/*** removes the directory, which belongs to a student/teacher
**** specified by dirname.
**** dirname must contain "people/" followed by a legitimate username
***/

void
remove_directory (const char *dirname)
{
  char *ptr;
  char *username;
  
  ptr = strstr(dirname, PEOPLE_DIR);
  if(ptr)
    {
     username = ptr + strlen(PEOPLE_DIR);
     if(*username == '/')
      {
        username++;
        if(!username_invalid(username))   /* shared_authenticate.c */
                 kill_directory(dirname);   /* shared_file_util.c */
      } 
    }
}    







