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

#include "global.h"

#include "manhat-lib/shared_util.h"
#include "manhat-lib/shared_cs_util.h"
#include "manhat-lib/shared_news_util.h"
#include "manhat-lib/shared_lock.h"
#include "manhat-lib/shared_file_util.h"


static void
read_parameters (char *course, char *key, long *offset, int *grp, char *team)
{

  char temp[20];

  
  cs_get_required_parameter ("validate", temp, 9);	/* shared_cgi_util.c */
  cs_get_required_parameter ("crs", course, MAX_PATH);	/* shared_cgi_util.c */
  cs_get_required_parameter ("id", key, MAX_KEY);
  cs_get_required_parameter ("grp", temp, 5);
  *grp = atoi (temp);
  cs_get_required_parameter ("loc", temp, 19);
  *offset = atol (temp);

  if (*grp == TEAM_TEACH)
    {
      cs_get_required_parameter ("team", temp, 5);
      *team = *temp;
    }
  else 
     *team = '!';    /* assign some arbitrary value to team to prevent 'unitialized value' compiler warning */  


}


static void
mark_deleted(MSG_TREE_NODE *msg)
{
 int fd;
 FILE *fp;
 char inbox_fname[MAX_PATH + 1];  /* full path to central inbox */
 CENTRAL_INBOX_RECORD data;
 
 snprintf(inbox_fname,MAX_PATH + 1,"%s%s",central_discussion_path,INBOX_FNAME);
 fp = fopen(inbox_fname,"r+");
 if(!fp)                              /* inbox.dat doesn't exist */
  cs_critical_error(ERR_FOPEN_READ_FAILED,"");
  
 fd = fileno(fp);
 get_exclusive_lock(fd, 1);                      /* shared_lock.c */

 /* read the msg we are working with */
 if(fseek(fp, msg->offset, SEEK_SET))
    cs_critical_error(ERR_FSEEK_FAILED,"");
 if(fread(&data, sizeof(CENTRAL_INBOX_RECORD),1,fp) != 1)
    cs_critical_error(ERR_FREAD_FAILED, "");
 
 data.status = DELETED;
 
 if(fseek(fp, msg->offset, SEEK_SET))
    cs_critical_error(ERR_FSEEK_FAILED,"");
 if(fwrite(&data, sizeof(CENTRAL_INBOX_RECORD),1,fp) != 1)
      cs_critical_error(ERR_FWRITE_FAILED, "");

 release_lock(fd);   /* shared_lock.c */
 fclose(fp);
}
 
  
static void
delete_files(MSG_TREE_NODE *msg, const char *course_path)
{
  FILE *fp;
  int fd;
  
  char infopath[MAX_PATH + 1];
  NEWS_INFO infofile_info;
  char deletepath[MAX_PATH + 1];
  int i;
  ATTACHMENT attachment;


  snprintf (infopath, MAX_PATH + 1, "%s%s/%s/%s/%s", course_path, PEOPLE_DIR, msg->data.info.sender, 
  					discussion_fname,msg->data.info_fname);
  fp = fopen (infopath, "r");
  if (!fp)
    return;			/* we'll ignore this error (?) */
  
  fd = fileno(fp);
  get_shared_lock(fd, 1);            /* shared_lock.c */
    
  if (fread (&infofile_info, sizeof (NEWS_INFO), 1, fp) != 1)
    cs_critical_error (ERR_READING_INFO, "");

 /*** delete the message file */
  snprintf (deletepath, MAX_PATH + 1, "%s%s/%s/%s/%s", 
                   course_path, PEOPLE_DIR, msg->data.info.sender, discussion_fname, infofile_info.msg_fname);


  unlink (deletepath);

  if (infofile_info.attachments == -1)
    {				/* a web page was attached */
      if (fread (&attachment, sizeof (ATTACHMENT), 1, fp) != 1)
	cs_critical_error (ERR_ERROR_READING_ATTACHMENT, "");
      snprintf (deletepath, MAX_PATH + 1, "%s%s/%s/%s/%s", 
                   course_path, PEOPLE_DIR, msg->data.info.sender, discussion_fname, attachment.unique_fname);
      kill_directory (deletepath);   /* shared_file_util.c */
    }
  else				/* a web page was not attached */
    for (i = 1; i <= infofile_info.attachments; i++)
      {
	if (fread (&attachment, sizeof (ATTACHMENT), 1, fp) != 1)
	  cs_critical_error (ERR_ERROR_READING_ATTACHMENT, "");
        snprintf (deletepath, MAX_PATH + 1, "%s%s/%s/%s/%s", 
                   course_path, PEOPLE_DIR, msg->data.info.sender, discussion_fname, attachment.unique_fname);
	unlink (deletepath);
      }


  release_lock(fd);
  fclose (fp);
  
  unlink (infopath);

}



static void
delete_one_message (MSG_TREE_NODE *msg, const char *course_path)
{
 mark_deleted(msg);
 delete_files(msg,course_path);
}


/* if the message we are deleting has one or more replies,
** we must change the reply_to value for those replies
** to the same value as the reply_to of the message
** we are deleting
*/
static void
adjust_replies (MSG_TREE_NODE *msg, const char *course_path)
{
 int fd;
 FILE *fp;
 char inbox_fname[MAX_PATH + 1];  /* full path to central inbox */
 CENTRAL_INBOX_RECORD data;
 MSG_TREE_NODE *reply;
  
 if(msg->reply)
 {
 
   snprintf(inbox_fname,MAX_PATH + 1,"%s%s",central_discussion_path,INBOX_FNAME);
   fp = fopen(inbox_fname,"r+");
   if(!fp)                              /* inbox.dat doesn't exist */
      cs_critical_error(ERR_FOPEN_READ_FAILED,"");
  
   fd = fileno(fp);
   get_exclusive_lock(fd, 1);                      /* shared_lock.c */

   for(reply=msg->reply; reply; reply=reply->next)
    {
     /* read the reply to the msg we are deleting */
     if(fseek(fp, reply->offset, SEEK_SET))
         cs_critical_error(ERR_FSEEK_FAILED,"");
     if(fread(&data, sizeof(CENTRAL_INBOX_RECORD),1,fp) != 1)
          cs_critical_error(ERR_FREAD_FAILED, "");
 
     data.info.reply_to = msg->data.info.reply_to;
 
     if(fseek(fp, reply->offset, SEEK_SET))
         cs_critical_error(ERR_FSEEK_FAILED,"");
     if(fwrite(&data, sizeof(CENTRAL_INBOX_RECORD),1,fp) != 1)
          cs_critical_error(ERR_FWRITE_FAILED, "");
    }
    
    release_lock(fd);   /* shared_lock.c */
    fclose(fp);
 } /* if msg has a reply */ 
}




static void
delete_msg_tree(MSG_TREE_NODE *root, const char *course_path)
{

 if(!root)
	 return;
 delete_one_message(root,course_path);
 delete_msg_tree(root->next,course_path);
 delete_msg_tree(root->reply,course_path);
}





static void
delete_message(SESSION *user, int grp, long offset, const char *course_path)
{
MSG_TREE_NODE *topic, *msg;
int msg_count;
time_t current_time;    /* needed for build_one_topic_tree call */

 build_one_topic_tree(user, grp, offset, &msg, &topic, &msg_count, 0, 1, &current_time);
 if(!msg || !tree_head)
   cs_critical_error(ERR_CANT_FIND_THIS_OFFSET, "");

 if(msg == topic)   /* if the message we want to delete is a topic */
   delete_msg_tree(topic,course_path);
 else
  {
   delete_one_message(msg,course_path);
   adjust_replies(msg,course_path);
  } 
   
 free_msg_tree(topic);
}

      
 


int
main (void)
{
  char course[MAX_PATH + 1];	/* from crs=? command line */
  char key[MAX_KEY + 1];	/* from id=? command line */
  long offset;                  /* from loc=? command line */
  int grp;			/* from grp=? command line */
  char team;			/* optional team=? command line req'd only for team_teach module */

  SESSION user;
  CONFIG_STRUCT conf;		/* the configuration read from config file */


  cs_cgi_init();
  read_parameters (course, key, &offset, &grp, &team);
  read_configuration_file (course, &conf);	/* shared_util.c */
  validate_key (key, &user, &conf);	/* shared_util.c */
   
  if (user.group != FACULTY)
    cs_critical_error (ERR_REQUEST_DENIED, "");

  /* if this is the TEAM_TEACH module, switch user to the team provided on the command line */
  if (grp == TEAM_TEACH)
      user.team = team;
      
  set_discussion_names (conf.course_path, user.username, grp);	/* shared_news_util.c */

  delete_message(&user, grp, offset, conf.course_path);

 if (grp == TEAM_TEACH)
    printf ("Location:%s?crs=%s&id=%s&grp=%d&team=%c\n\n", "news_topic", course,
	    key, grp, team);
  else
    printf ("Location:%s?crs=%s&id=%s&grp=%d\n\n", "news_topic", course, key,
	    grp);
  cs_cgi_destroy(); 
  return 0;
}

