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

#include "global.h"
#include "custom.h"

#include "manhat-lib/shared_util.h"
#include "manhat-lib/shared_cs_util.h"
#include "manhat-lib/shared_read_infofile.h"
#include "manhat-lib/shared_person_list.h"
#include "manhat-lib/shared_news_util.h"
#include "manhat-lib/shared_clipboard_util.h"
#include "manhat-lib/shared_translate_url.h"
#include "manhat-lib/shared_access.h"
#include "manhat-lib/shared_spelling_util.h"
#include "manhat-lib/shared_lock.h"


ATTACHMENT_NODE *pasted_attachment_head = 0;	/* linked list of file info, used for pasting */



/** The 'paste' parameter is optional, and is used to flag whether or 
*** not this program was called because someone (a teacher) clicked on 
*** the "Paste from clipboard' button.
***
*** Two additional optional parameters work together: loc and grp.
*** if loc parameter does not exist, 
****       then this is not a reply.  
**** Otherwise
***        - the loc parameter represents the file offset
***          at which the message we are replying to is located
***        - the 'grp' parameter is now required.  It's a 0/1
***          value, which tells whether or not this is a "Group Reply"
**/

static void
get_optional_parameters (long *reply_offset, int *group_reply, int *paste)
{
  char value[20];
  
  
  cs_get_optional_parameter("paste", value, 19);
  if (!*value)
    *paste = 0;
  else
    *paste = (*value == 'Y' || *value == 'y');

  cs_get_optional_parameter("loc", value, 19);
  if (!*value)			/* loc param not found, assume not a reply */
    *reply_offset = -1;		/* -1 means this is not a reply */
  else
    {
      *reply_offset = atol (value);
      cs_get_required_parameter("grp", value, 19);
      *group_reply = atoi (value);
    }


}




static void
read_parameters (char *course, char *key,
		 char *from_prog, long *reply_offset, int *group_reply, int *paste)
{

  cs_get_required_parameter ("crs", course, MAX_PATH);
  cs_get_required_parameter ("id", key, MAX_KEY);
  cs_get_required_parameter ("from", from_prog, MAX_PATH);
  get_optional_parameters (reply_offset, group_reply, paste);

}




static void
set_basic_data (char *course, char *key, char *from, long reply_offset, int group_reply,
                                       CONFIG_STRUCT *conf, SESSION *user)
{
  char temp[MAX_PATH + 1];
  int empty_clipboard;


  cs_set_value("crs", course);
  cs_set_value("id", key);
  
  
  cs_set_course_info(conf);         /* shared_cs_util.c */
  cs_set_current_time();            /* shared_cs_util.c */

  
 /** clipboard_empty() is in shared_clipboard_util.c */
  empty_clipboard = (user->group != FACULTY)
                       || clipboard_empty (user->username, conf->course_path, user);
  cs_set_int_value("content_clipboard", empty_clipboard? 0 : 1);



  translate_url_substitutes (temp, from, MAX_PATH + 1,1);	/* shared_translate_url.c */
  cs_set_value("from", from);
  cs_set_value("back_url", temp);
  
  /* If the value of reply_offset is not -1 , then this is a reply */
  if(reply_offset == - 1)
   {
    cs_set_int_value("is_reply", 0);
   }
  else
   {
     cs_set_int_value("is_reply", 1);
   
     snprintf(temp, MAX_PATH, "%ld", reply_offset);
     cs_set_value("reply_offset", temp);
     
     cs_set_int_value("is_group_reply", group_reply? 1: 0);
   }
  
  cs_set_int_value("msg.textarea.cols", editor_width_config(conf->misc));    /* shared_news_util.c */
  cs_set_int_value("msg.textarea.hard_wrap", USE_TEXTAREA_HARD_WRAP); 
  cs_set_int_value("msg.subject.max", MAX_SUBJECT - 1);
  cs_set_int_value("msg.subject.size", MAX_SUBJECT - 1);  
  

}



void
new_memo_attach (int add_note, CONFIG_STRUCT *conf)
{

  if (add_note)
     cs_set_int_value("attach.add_note", 1);
  cs_set_int_value("attach.max_files", conf->mail_attachments);

}


static void
process_inbox (long offset, INBOX_RECORD * inbox, INFO * infofile_info,
               CONFIG_STRUCT *conf, SESSION *user)
{
  char inbox_path[MAX_PATH + 1];
  FILE *fp;

  snprintf (inbox_path, MAX_PATH + 1, "%s%s/%s/%s/%s", conf->course_path,PEOPLE_DIR,
	    user->username, MAIL_DIR, INBOX_FNAME);
  fp = fopen (inbox_path, "r+");
  if (!fp)
    cs_critical_error (ERR_FOPEN_APPEND_FAILED, "");
    
  get_exclusive_lock(fileno(fp), 1);     /* shared_lock.c */
  if (fseek (fp, offset, SEEK_SET))
    cs_critical_error (ERR_FSEEK_FAILED, "");
  if (fread (inbox, sizeof (INBOX_RECORD), 1, fp) != 1)
    cs_critical_error (ERR_FREAD_FAILED, "");
    
  release_lock(fileno(fp));  /* shared_lock.c */
  fclose (fp);

  /*** now read the info file- see shared_read_info.c  */
  read_post_infofile (inbox->newfile_info.sender,
		      inbox->newfile_info.info_fname, infofile_info, conf);
}





/* creates a textarea field which is one char wider than the longest line
** of the message to allow for insertion of > char
*/

static void
do_reply_textarea (const char *sender_username, const char *msg_fname,
                   CONFIG_STRUCT *conf)
{
  FILE *fp;
  char fullpath[MAX_PATH + 1];
  int longest;
  struct stat file_stat;
  char *buf =0, *add_reply_mark =0;

  snprintf (fullpath, MAX_PATH + 1, "%s/%s/%s/%s/%s",
	    conf->course_path, PEOPLE_DIR,sender_username, MAIL_DIR, msg_fname);
  if(stat(fullpath, &file_stat))
    cs_critical_error (ERR_STAT_FAILED, "");
	
  buf = (char *)malloc((file_stat.st_size +1)*sizeof(char));
  if(!buf)
    cs_critical_error (ERR_MALLOC_FAILED, "");

  fp = fopen (fullpath, "r");
  if (!fp)
    cs_critical_error (ERR_FOPEN_READ_FAILED, "");

  fread(buf, file_stat.st_size, 1, fp);
  
   *(buf + file_stat.st_size ) = '\0';
  fclose (fp);
  
  longest = find_longest_line(buf, conf);                     /* shared_news_util.c */
  cs_set_int_value("msg.textarea.cols", longest + 1);
  longest = find_num_lines(buf);                        /* shared_news_util.c */
  if(strlen(buf))
  {
    add_reply_mark = add_mark_to_msg(buf, longest);     /* shared_news_util.c */
    cs_set_value("msg.textarea.body", add_reply_mark);
  }
  if(buf)
	free(buf);
  if(add_reply_mark)
	free(add_reply_mark);
}





static int
get_post_clipboard_info (CLIPBOARD_INFO * clipboard_info, char *clipboard_path,
                         SESSION *user)
{
  char fullpath[MAX_PATH + 1];
  ATTACHMENT_NODE *aptr = 0;
  int i;
  FILE *fp;

  snprintf (clipboard_path, MAX_PATH + 1, "%s%s/", CLIPBOARD_PATH, user->id);
  snprintf (fullpath, MAX_PATH + 1, "%s%s", clipboard_path,
	    CLIPBOARD_INF_FNAME);
  fp = fopen (fullpath, "r");
  if (!fp)
    return 1;
  if (fread (clipboard_info, sizeof (CLIPBOARD_INFO), 1, fp) != 1)
    {
      fclose (fp);
      return 1;
    }

  /* now read attachment records */

  if (clipboard_info->attachments == -1)	/* -1 flags a website attached */
    clipboard_info->attachments = 1;	/* change -1 to 1 for the next 'for' loop */

  for (i = 1; i <= clipboard_info->attachments; i++)
    {
      if (!pasted_attachment_head)
	{
	  pasted_attachment_head =
	    (ATTACHMENT_NODE *) malloc (sizeof (ATTACHMENT_NODE));
	  if (!pasted_attachment_head)
	    cs_critical_error (ERR_MALLOC_FAILED, "");
	  aptr = pasted_attachment_head;
	}
      else
	{
	  aptr->next = (ATTACHMENT_NODE *) malloc (sizeof (ATTACHMENT_NODE));
	  if (!aptr->next)
	    cs_critical_error (ERR_MALLOC_FAILED, "");
	  aptr = aptr->next;
	}

      if (fread (&aptr->data, sizeof (ATTACHMENT), 1, fp) != 1)
	cs_critical_error (ERR_FREAD_FAILED, "");
      aptr->next = 0;
    }				/* for .. */



  fclose (fp);
  return 0;
}





static void
free_pasted_attachment_list ()
{
  ATTACHMENT_NODE *aptr;

  while (pasted_attachment_head)
    {
      aptr = pasted_attachment_head;
      pasted_attachment_head = pasted_attachment_head->next;
      free (aptr);
    }
}

static int
do_paste (int *files_attached, SESSION *user,  CONFIG_STRUCT *conf)
{
 #define MAX_TMP_NAME 30
  CLIPBOARD_INFO clipboard_info;
  char clipboard_path[MAX_PATH + 1];
  char  *clip_subject =0;
  ATTACHMENT_NODE *aptr;
  int i;
  char name[MAX_TMP_NAME + 1];
  char value[MAX_PATH +1];

  *files_attached = 0;		/* assume this to start */

  if (user->group != FACULTY)
    cs_critical_error (ERR_REQUEST_DENIED, "");

  if (get_post_clipboard_info (&clipboard_info, clipboard_path, user))
    return 1;			/* clipboard is empty */
    
    
  cs_set_int_value("do_clipboard", 1);

  *files_attached = clipboard_info.attachments;

  /* handle subject */
  clip_subject = replace_quot(clipboard_info.subject);    /* shared_news_util.c */
  cs_set_value("msg.subject.value", clip_subject);
  free(clip_subject);
  
  /* do_paste_textarea() is in shared_news_util.c*/
  do_paste_textarea (clipboard_path, clipboard_info.msg_fname,
		     clipboard_info.sender_username,
		     clipboard_info.sender_realname, user, conf);
  
  if (pasted_attachment_head)
    {
      cs_set_int_value("has_attach", 1);
      if(clipboard_info.website_attached && 
                              is_hotpot_exam_dir(pasted_attachment_head->data.unique_fname))  /* shared_news_util.c */
	      cs_set_int_value("attach.not_allow", 1);
      else
       {
	   
	   if(clipboard_info.website_attached) 
	   {
	      cs_set_value("attach.type", "pasted_website");
	      cs_set_int_value("attach.value", 1);
	      cs_set_int_value("attach.website", 1);
	   }
	   else
	   {
	      cs_set_value("attach.type", "pasted_files");
	      cs_set_int_value("attach.value", clipboard_info.attachments);
	   }


        for (i = 1, aptr = pasted_attachment_head; aptr; aptr = aptr->next, i++)
	{
	     snprintf(name, MAX_TMP_NAME, "attach.file.%d.value", i-1);
	     snprintf(value, MAX_PATH, "%s::%s", aptr->data.orig_fname, aptr->data.unique_fname);
	     cs_set_value(name, value);
             if(i == 1 && clipboard_info.website_attached)
	     {
		 snprintf(name, MAX_TMP_NAME, "attach.file.%d.type", i-1);
		 cs_set_int_value(name, 1);
	     }
	     else
	     {
		 snprintf(name, MAX_TMP_NAME, "attach.file.%d.orig", i-1);
		 cs_set_value(name, aptr->data.orig_fname);
	     }
	}
       }  
      free_pasted_attachment_list ();
      
    }
  return 0;			/* paste successful */
 #undef MAX_TMP_NAME 

}





static void
set_new_memo_form (char *course, char *key, char *from_prog,
		       long reply_offset, int group_reply, int paste,
                       CONFIG_STRUCT *conf, SESSION *user)
{
  INBOX_RECORD inbox;
  INFO infofile_info;
  char reply_subject[MAX_SUBJECT + 1];
  int paste_failed = 0;
  int files_attached = 0;
  char *subject = 0;
  P_NODE *p;
  
  
  set_basic_data (course, key, from_prog, reply_offset, group_reply, conf, user);
  insert_spell_check_button(conf); /* shared_spelling_util.c */ 
  
  cs_set_int_value("emoticons_disabled", EMOTICONS_DISABLED(conf->misc)? 1 : 0);

  p = build_option_person_list (conf);	/* shared_person_list.c */
  
  if(!ALLOW_POST_OFFICE_MSGS_TO_SELF)             	/* see custom.h */
      p = option_list_remove_user( p, user->username);  /* shared_person_list.c */

  set_option_userlist(p);               /* shared_person_list.c */
  
  if (paste)
      paste_failed = do_paste (&files_attached, user, conf);


  if (!paste || paste_failed)
    {
      if ((reply_offset == -1) || paste_failed)
	{			/* i.e. if this is not a reply */
                               /* do nothing  */
 	}
      else
	{			/* this is a reply or a group reply */
	  process_inbox (reply_offset, &inbox, &infofile_info, conf, user);	/* need to know who to send it to */
	  if (!group_reply)
	    {		
	      /* To: gets sender's name preselected */
               set_post_recipient(TO, inbox.newfile_info.sender,inbox.newfile_info.sender_realname);   /* shared_person_list.c */
	    }
	  else
	    {	
              set_post_group_reply_recipients(inbox.newfile_info.sender, inbox.newfile_info.sender_realname, 
                                                                       user->username, person_head);
	    }

  
	  /* handle subject */
	  cs_set_int_value("msg.subject.add_re", 1);
	  strncpy (reply_subject, inbox.newfile_info.subject, MAX_SUBJECT+1);
         
	  /* set subject but must replace quotes " with &quot; */
           subject = replace_quot(reply_subject);         /* shared_news_util.c */
           cs_set_value("msg.subject.value", subject);    
           if(subject)
               free(subject);

	  /* handle textarea */
	  do_reply_textarea (inbox.newfile_info.sender,
			     infofile_info.msg_fname, conf);
          cs_set_value("msg.textarea.author", inbox.newfile_info.sender_realname);
          
	}			/* else: if reply */
    }				/* if(!paste || paste_failed) */

  free_option_person_list (p);	/* shared_person_list.c */
  new_memo_attach (files_attached, conf);

}







int
main (void)
{
  char course[MAX_PATH + 1];		/* from crs=? command line */
  char key[MAX_KEY + 1];		/* from id=? command line */
  char from_prog[MAX_PATH + 1];		/* from from=? cmd line */
  long reply_offset;			/* from loc=? optional cmd line */
  int group_reply = 0;			/* from grp=? optional cmd line */
  int paste;				/* from paste=? optional cmd line */
  SESSION user;
  CONFIG_STRUCT conf;			/* the configuration read from config file */

  cs_cgi_init();

  read_parameters (course, key, from_prog, &reply_offset, &group_reply, &paste);
  
  read_configuration_file (course, &conf);	/* shared_util.c */
  validate_key (key, &user, &conf);	        /* shared_util.c */
  
  if(!has_write_permission(&user, &conf))       /* shared_access.c */
      access_denied_error();

  
  set_new_memo_form (course, key, from_prog, reply_offset, group_reply, paste, &conf, &user);


  cs_cgi_display("post_new_memo", 1);
  cs_cgi_destroy();
  return 0;
}

