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

#include "global.h"
#include "custom.h"		/* for date FORMAT strings */
#include "survey.h"

#include "manhat-lib/shared_util.h"
#include "manhat-lib/shared_lock.h"
#include "manhat-lib/shared_news_util.h"
#include "manhat-lib/shared_file_util.h"
#include "manhat-lib/shared_cs_util.h"
#include "manhat-lib/shared_time.h"
#include "manhat-lib/shared_copy_file.h"
#include "manhat-lib/shared_person_list.h"
#include "manhat-lib/shared_fold_file.h"
#include "manhat-lib/shared_podcast_util.h"


void check_upload_file()
{
    FILE *fp;
    struct stat file_stat;

    char *filename = hdf_get_value(global_cgi->hdf, "Query.podcasting", 0);

    if(!filename)
	 cs_critical_error(ERR_PARAM_MISSING, "podcasting");
    fp = cgi_filehandle(global_cgi, "podcasting");
    if(!fp)
	cs_critical_error(ERR_NO_FILE, "check_upload_file");
    if(fstat(fileno(fp), &file_stat))
	cs_critical_error(ERR_NO_FILE, "check_upload_file");
    if(file_stat.st_size == 0)
	cs_critical_error(ERR_NO_FILE, "check_upload_file");
	
}



static
char* read_parameters (char *course, char *key, int *hide, 
		       char *subject, int *width, int *is_pasted)
{
   char tmp[80], filename[MAX_PATH], extension[MAX_FILENAME+1], pasted_file[MAX_PATH +1];
   char *string;
   char *msg;
   
   

   cs_get_required_parameter ("crs", course, MAX_PATH);
   cs_get_required_parameter ("id", key, MAX_KEY);
   cs_get_required_parameter ("subject", subject, MAX_SUBJECT);
   cs_get_required_parameter ("width", tmp, 79);
   *width = atoi(tmp);


   cs_get_optional_parameter ("podcasting", filename, MAX_PATH);
   cs_get_optional_parameter ("pod_paste", pasted_file, MAX_PATH);

   if(!strlen(filename) && (!strlen(pasted_file) || !strcmp(pasted_file, "-1")))
	 cs_critical_error(ERR_PODCASTING_NEED_ONE_FILE, "empty string");
   else if(strlen(filename) && strlen(pasted_file) && strcmp(pasted_file, "-1")  )
	 cs_critical_error(ERR_PODCASTING_NEED_ONE_FILE, "both not empty");

   if(strlen(filename))
   {
      get_extension(filename, extension);   /* shared_news_util.c */
      if( !is_valid_podcast_file_extension(extension))   /* shared_podcast_util.c */
	cs_critical_error(ERR_PODCASTING_FILE_FORMAT, "podcasting_send_mail");
      check_upload_file();
      *is_pasted = 0;
   }
   else if( strcmp(pasted_file, "-1"))
      *is_pasted = 1;

   cs_get_optional_parameter ("hide", tmp, 19);
   if(strlen(tmp)>0)
      *hide = 1;
   else
      *hide =0;
   string = hdf_get_value(global_cgi->hdf, "Query.msg", 0);
   if(!string)
    {
      msg = (char *) malloc(sizeof(char)*2);
      if(!msg)
         cs_critical_error(ERR_MALLOC_FAILED, "");
      *msg= '\0';
    }
   else
    {
     msg = (char *) malloc( (strlen(string) + 1) * sizeof(char));
     if(!msg)
         cs_critical_error(ERR_MALLOC_FAILED, "");
     strcpy(msg,string);      
    }
     
       
   return msg;
     
}


static void
write_msg_file ( char *msg, const char *unique_fname, int width)
{
  FILE  *outfp;
  char filepath[MAX_PATH + 1];
  int len =0;

  snprintf (filepath, MAX_PATH + 1, "%s/%s", discussion_path, unique_fname);
  if(msg)
    len = strlen(msg);
  outfp = fopen (filepath, "w");
  if (!outfp)
    cs_critical_error (ERR_FOPEN_WRITE_FAILED, "");

  if(len < width || USE_TEXTAREA_HARD_WRAP)
     fprintf (outfp, "%s", msg);
  else
    write_folded(outfp, msg, width);    /* shared_fold_file.c */
  fclose (outfp);
}




/* note that this creates the file */
void
get_unique_fname(char *unique_fname, const char *base_dir, const char *filetype, time_t *time_sent)
{
 int fd;
 
 fd = get_unique_fd(base_dir, filetype, unique_fname, time_sent);
 close(fd);
} 



static void
process_message_file ( char *msg,  char *msg_fname, time_t * time_sent, int width)
{
    get_unique_fname (msg_fname, discussion_path, "msg", time_sent);
    write_msg_file (msg, msg_fname, width);
}







static void
complete_send (const char *msg_fname, SESSION *user, time_t time_sent, int hide, const char *subject,
			const char *unique, const char *org)
{
  FILE  *inbox_fp;
  int info_fd, inbox_fd;
  struct stat buf;
  NEWS_PERSON person;
  
  char info_fname[MAX_FILENAME + 1];
  char inbox_fname[MAX_PATH + 1];
  int msg_id;
  CENTRAL_INBOX_RECORD inbox_record, new_inbox_record;
  int inbox_record_size,  attachment_size;
  
  ATTACHMENT attach;
  
 /* memorize the sizes of these data structures, 
 ** so we don't have to repeatedly call sizeof()
 */
  inbox_record_size = sizeof(CENTRAL_INBOX_RECORD); 
  attachment_size = sizeof(ATTACHMENT);
  
 /* this user has already read this message
 ** set a NEWS_PERSON record to be written
 ** to the end of the new inf file.
 */
 strncpy(person.username,user->username, MAX_USERNAME + 1);
 strncpy(person.realname, user->realname, MAX_NAME + 1);
 person.time_read = time_sent;
 person.user_unlocked = 0;


  /* set up as much of the new inbox record as we can before locking
  ** the inbox.dat file
  */  
  strncpy(new_inbox_record.info.msg_fname, msg_fname, MAX_FILENAME + 1);
  strncpy(new_inbox_record.info.sender, user->username, MAX_USERNAME + 1);
  strncpy(new_inbox_record.info.sender_realname, user->realname, MAX_NAME + 1);
  strncpy(new_inbox_record.info.receiver_username,"",MAX_USERNAME + 1);  
  strncpy(new_inbox_record.info.subject, subject, MAX_SUBJECT + 1);
  new_inbox_record.info.time_sent = time_sent;
  new_inbox_record.info.attachments = 1;      
  new_inbox_record.info.sender_team = user->team;
  new_inbox_record.info.reply_to = -1;
  
  /* get the name of the 'inf' file to do so, we need to open
  ** (create) the file
  */
  info_fd = get_unique_fd (discussion_path,"inf", info_fname, &time_sent);
  /* don't bother to lock it, since no one knows it's there yet! */
  
  strncpy(new_inbox_record.info_fname,info_fname,MAX_FILENAME + 1);
  new_inbox_record.release_time = 0;      
  new_inbox_record.unrelease_time = 0;
  new_inbox_record.status =  hide? TEACHER_HIDDEN: NORMAL;      
  
  /* now open and lock the inbox.dat file */
  snprintf(inbox_fname,MAX_PATH + 1,"%s%s",central_discussion_path,INBOX_FNAME);
  inbox_fp = fopen(inbox_fname,"a+");
  if(!inbox_fp)                              /* couldn't open or create inbox.dat */
    cs_critical_error(ERR_FOPEN_WRITE_FAILED, inbox_fname);
  inbox_fd = fileno(inbox_fp);
  get_exclusive_lock(inbox_fd, 1);                      /* shared_lock.c */
  
  
  /* get the next available msg_id, by incrementing the msg_id of the
  ** last msg in the inbox.dat file
  */
  fstat(inbox_fd, &buf);
  if(!buf.st_size)    /* this is the first message */
     msg_id = 1;
  else
    {
     if(fseek(inbox_fp,-inbox_record_size,SEEK_END) == -1)
       cs_critical_error(ERR_FSEEK_FAILED, "");
     if(fread( &inbox_record, inbox_record_size, 1, inbox_fp) != 1)
       cs_critical_error(ERR_FREAD_FAILED, "");
     msg_id =  inbox_record.info.msg_id + 1;
    }
    
   new_inbox_record.info.msg_id = msg_id;
   new_inbox_record.info.topic_id =  msg_id;
   if(fseek(inbox_fp,0,SEEK_END) == -1)
     cs_critical_error(ERR_FSEEK_FAILED, "");
   if(fwrite(&new_inbox_record, inbox_record_size,1,inbox_fp) != 1)
      cs_critical_error(ERR_FWRITE_FAILED, "");



  /* now write the info file */   
  if (write (info_fd, &new_inbox_record.info, sizeof (NEWS_INFO)) != sizeof(NEWS_INFO))
    cs_critical_error (ERR_FWRITE_FAILED, "");

  strncpy (attach.unique_fname, unique, MAX_FILENAME + 1);
  strncpy (attach.orig_fname, org, MAX_FILENAME + 1);
  if (write (info_fd, &attach, attachment_size) != attachment_size)
	cs_critical_error (ERR_FWRITE_FAILED, "");


   if(write (info_fd,&person, sizeof(NEWS_PERSON))!= sizeof(NEWS_PERSON))
        cs_critical_error (ERR_FWRITE_FAILED, "");
        

   release_lock(inbox_fd);     /* shared_lock.c */
   fclose(inbox_fp);
   
   write_user_inbox_record(msg_id, time_sent);    /* shared_news_util.c */
}
     
static int
student_count(CONFIG_STRUCT *conf)
{
 P_NODE *head;
 int count;
 
 head = build_option_person_list(conf);   /* shared_person_list.c */
 count = count_students(head);           /* shared_person_list.c */
 free_option_person_list(head);          /* shared_person_list.c */
 return count;
} 
  

void upload_podfile(char *unique_fname, char *orig_fname, time_t *time_sent) 
{
     char filename[MAX_PATH +1];
     FILE *fp;
     struct stat file_stat;

     cs_get_required_parameter("podcasting", filename, MAX_PATH );


     get_unique_fname (unique_fname, discussion_path, "fil", time_sent); /* shared_news_util.c */
     get_orig_fname (filename, orig_fname);  /* shared_news_uitl.c */


    fp = cgi_filehandle(global_cgi, "podcasting");

    if(!fp)
	cs_critical_error(ERR_NO_FILE, "upload_podfile");
    if(fstat(fileno(fp), &file_stat))
	cs_critical_error(ERR_NO_FILE, "upload_podfile");
    
    write_cgi_file (fp, file_stat.st_size, unique_fname);

}


static void
parse_raw_filename (char *raw_fname, char *orig_fname, char *unique_fname)
{
  char *ptr;

   ptr = strstr (raw_fname, "::");
   if (!ptr)
         cs_critical_error (ERR_PARAM_FORMAT, raw_fname);
   *ptr = '\0';
   strncpy (orig_fname, raw_fname, MAX_FILENAME + 1);
   ptr += 2;                     /* skip past "::" */
    strncpy (unique_fname, ptr, MAX_FILENAME + 1);
}

void handle_pasted_file(char *unique_fname, char *origional_fname, time_t *time_sent, SESSION *user)
{
  char raw_fname[MAX_PATH +1];
  char pasted_origfname[MAX_FILENAME +1];
  char pasted_uniquefname[MAX_FILENAME +1];
  char sourcepath[MAX_PATH +1];
  char destpath[MAX_PATH +1];
  char clipboard_path[MAX_PATH +1];

  
  cs_get_required_parameter("pod_paste", raw_fname, MAX_PATH);  
  parse_raw_filename (raw_fname, pasted_origfname, pasted_uniquefname);
  strncpy(origional_fname, pasted_origfname, MAX_FILENAME +1);
  get_unique_fname (unique_fname, discussion_path, "fil", time_sent); /* shared_news_util.c */

  snprintf (clipboard_path, MAX_PATH + 1, "%s%s/", CLIPBOARD_PATH, user->id);

  snprintf (sourcepath, MAX_PATH + 1, "%s%s", clipboard_path,pasted_uniquefname);
  snprintf (destpath, MAX_PATH + 1, "%s%s", discussion_path,unique_fname);
  copy_file (sourcepath, destpath); /* shared_copy_file.c */
}



int
main (void)
{
  char course[MAX_PATH + 1];	/* from crs=? command line */
  char key[MAX_KEY + 1];	/* from id=? command line */
  int hide;                     /* from hide=? command line */
  char subject[MAX_SUBJECT +1]; /*from subject= command line */
  char *msg;                   /* from msg = command line */

  char unique_filename[MAX_FILENAME + 1];  /* mkstemp() name given to the  directory where the survey
                                      ** xml files are copied
                                      */
  char origional_filename[MAX_FILENAME + 1]; 
  int is_pasted =0;  
  time_t  time_sent;
  char msg_fname[MAX_FILENAME + 1];    /* mkstemp() name given to the msg file */
  int number_students;                 /* how many students are in this class ? */                               
  int width;  
  SESSION user;
  CONFIG_STRUCT conf;		/* the configuration read from config file */
  
  cs_cgi_init();
  msg =  read_parameters (course, key, &hide, subject, &width, &is_pasted);
  
  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, "");

  set_discussion_names (conf.course_path, user.username, PODCASTS);	/* #included */
 


  time_sent = time (NULL);
  process_message_file (msg, msg_fname, &time_sent, width);  /* writes the message */

  number_students = student_count(&conf);
  if(is_pasted == 0) 
     upload_podfile(unique_filename, origional_filename, &time_sent); 
  else
     handle_pasted_file(unique_filename, origional_filename, &time_sent, &user);

  complete_send(msg_fname,&user,time_sent,hide, subject, unique_filename, origional_filename);
  if(msg)
      free(msg);


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



