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

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


#define NOTEAM '!'		/* flag meaning that there was no 'team' parameter sent to this program */


#include "manhat-lib/shared_util.h"
#include "manhat-lib/shared_cs_util.h"
#include "manhat-lib/shared_news_util.h"
#include "manhat-lib/shared_person_list.h"
#include "manhat-lib/shared_translate_url.h"






typedef struct topic_node
{
  int total_msgs;
  int total_unread;
  int total_flagged;
  int teacher_hidden;
  MSG_TREE_NODE *topic_head;
  struct topic_node *next;
  struct topic_node *prev;
}
TOPIC_NODE;


TOPIC_NODE *topic_head = 0;
TOPIC_NODE *topic_tail = 0;



#define MAX_TEAMPART 20

typedef struct common_data
{
 char course[MAX_PATH + 1];
 char key[MAX_KEY + 1];
 int grp;
 char fromstring[MAX_PATH + 1];
 char teampart[MAX_TEAMPART + 1];
 int no_topic_type;
 char team;
 int is_fac_teamteach;
 int is_fac_assignments;
} COMMON_DATA;

COMMON_DATA common;

 

static void
read_topic_parameters ()
{
  char msg[80];

  cs_get_required_parameter ("crs", common.course, MAX_PATH);	/* shared_cgi_util.c */
  cs_get_required_parameter ("id", common.key, MAX_KEY);
  cs_get_required_parameter ("grp", msg, 5);
  common.grp = atoi (msg);

}






static void
set_general_values (CONFIG_STRUCT *conf, SESSION *user)
{
   char url[MAX_PATH +1];
   
   cs_set_course_info(conf);
   cs_set_current_time();
  if (common.is_fac_teamteach)
    snprintf (url, MAX_PATH +1, "%s?crs=%s&amp;id=%s&amp;grp=%d&amp;team=%c", "news_topic", common.course, common.key,
                                  common.grp, common.team);

  else
    snprintf (url, MAX_PATH +1, "%s?crs=%s&amp;id=%s&amp;grp=%d", "news_topic", common.course, common.key, common.grp);
  cs_set_value("back_url", url); 
  
  cs_set_int_value("grp", common.grp);
  
  cs_set_value("crs",common.course);
  cs_set_value("id", common.key);

  if (common.is_fac_teamteach)
  {
    snprintf(url, 5, "%c",common.team);
    cs_set_value("team", url);
  }


   cs_set_value("grp_uses_topics", common.no_topic_type? "0":"1");
   


}






/* assumes build_msg_tree() has already been called */
static void
build_topic_list (time_t current_time)
{
  TOPIC_NODE *ptr = 0;
  MSG_TREE_NODE *topic_ptr;
  int total_msgs = 0;
  int total_unread = 0;
  int total_flagged = 0;
  
  for(topic_ptr = tree_head; topic_ptr; topic_ptr=topic_ptr->next)
   {	  
    if (!topic_head)
    {
      topic_head = (TOPIC_NODE *) malloc (sizeof (TOPIC_NODE));
      if(!topic_head)
	 cs_critical_error(ERR_MALLOC_FAILED,"");
       ptr = topic_head;
       ptr->prev = 0;
    }
    else
    {
      ptr->next = (TOPIC_NODE *) malloc (sizeof (TOPIC_NODE));
      if(!ptr->next)
	 cs_critical_error(ERR_MALLOC_FAILED, "");
      ptr->next->prev = ptr;
      ptr = ptr->next;
    }
   
   
   count_topic_msgs(topic_ptr,&total_msgs, &total_unread, &total_flagged);   /* shared_news_util.c */
   ptr->total_msgs = total_msgs;
   ptr->total_unread = total_unread;

   ptr->total_flagged = total_flagged;
   
   ptr->teacher_hidden = 
           is_teacher_hidden (topic_ptr->data.status, topic_ptr->data.release_time,   /* shared_news_util.c */
                              topic_ptr->data.unrelease_time, current_time);

   ptr->topic_head = topic_ptr;
   ptr->next = 0;
   topic_tail = ptr;
   total_msgs = 0;
   total_unread = 0;
   total_flagged = 0;
   }
}


	
static void
free_topic_list ()
{
  TOPIC_NODE *ptr;

  while (topic_head)
    {
      ptr = topic_head;
      topic_head = topic_head->next;
      free(ptr);
    } 
}





static void
get_fromstring ()
{
  /* AMP_SUB, et. al. are #defined in shared_translate_url.h */
  snprintf (common.fromstring, MAX_PATH + 1, "%s%ccrs%c%s%cid%c%s%cgrp%c%d",
	    "news_topic", QMARK_SUB, EQUAL_SUB, common.course, AMP_SUB, EQUAL_SUB, common.key,
	    AMP_SUB, EQUAL_SUB, common.grp);

  if (common.team != NOTEAM)
    {
      snprintf (common.teampart, MAX_TEAMPART, "%cteam%c%c", AMP_SUB, EQUAL_SUB, common.team);
      strcat (common.fromstring, common.teampart);
      snprintf (common.teampart, MAX_TEAMPART, "&team=%c", common.team);	/* so we can use it directly */
    }
  else
    *common.teampart = '\0';
}





static void
set_message_data (TOPIC_NODE *ptr, time_t now, const char *teamstring)
{
#define  MAX_TMP_NAME 40
  char timestring[MAX_TIMESTRING + 1];
  static int i =0;
  char name[MAX_TMP_NAME +1]; 
  char *escaped_subject = (char *) 0;
  char offset_string[MAX_TMP_NAME + 1];
  int basic_status;
  
  snprintf(name, MAX_TMP_NAME, "message.%d.msg_id", i);
  cs_set_int_value(name,  ptr->topic_head->data.info.msg_id);


  snprintf(name, MAX_TMP_NAME, "message.%d.offset", i);
  snprintf(offset_string,MAX_TMP_NAME,"%ld", ptr->topic_head->offset);
  cs_set_value(name,offset_string);

  
  snprintf(name, MAX_TMP_NAME, "message.%d.teacher_hidden", i);
  cs_set_value(name, ptr->teacher_hidden? "1":"0");
     


  /* should the HTML page provide a means for the teacher to lock
  ** the attachments to this message?
  **/ 
  snprintf(name, MAX_TMP_NAME, "message.%d.allow_locked_attachments", i);
 
 /* if there are no attachments, or if this is the
 *** ANONYMOUS or SURVEYS module, don't allow user
 ** to set the attachment protection feature
 */
 if(!ptr->topic_head->data.info.attachments ||
    common.grp == ANONYMOUS_DISCUSSION     ||
    common.grp == SURVEYS || common.grp == INTERNET_RESOURCES)
 {    
   cs_set_value(name, "0");    /* don't allow locked attachments */
 }
 else
  { 
    cs_set_value(name, "1");    /* allow locked attachments */
  }    




  /* are the attachments to this message currently locked? */
  snprintf(name, MAX_TMP_NAME, "message.%d.attachments_locked", i);
  cs_set_value(name, IS_PROTECTED(ptr->topic_head->data.status) ? "1" : "0");


  /* how many messages are associated with this topic?  */
   snprintf(name, MAX_TMP_NAME, "message.%d.total_msgs", i);
   cs_set_int_value(name, ptr->total_msgs);


   /* how many UNREAD messages are associated with this topic? */
   snprintf(name, MAX_TMP_NAME, "message.%d.total_unread", i);
   cs_set_int_value(name, ptr->total_unread);


   /* how many FLAGGED messages are associated with this topic? */
   snprintf(name, MAX_TMP_NAME, "message.%d.total_flagged", i);
   cs_set_int_value(name, ptr->total_flagged);



  /* did this user already read THIS message? */
  if(!ptr->topic_head->user_data.time_read)
  {
      snprintf(name, MAX_TMP_NAME, "message.%d.is_unread", i);
      cs_set_value(name, ptr->topic_head->user_data.time_read? "0":"1");
  }


  /* did this user flag THIS message? */
  if(ptr->topic_head->user_data.flagged)
  {
      snprintf(name, MAX_TMP_NAME, "message.%d.is_flagged", i);
      cs_set_value(name, ptr->topic_head->user_data.flagged? "1":"0");
  }
  
  
  
 /* are there any attachments to this message */
 snprintf(name, MAX_TMP_NAME, "message.%d.has_attachments", i);
 cs_set_value(name, ptr->topic_head->data.info.attachments? "1" : "0" );


 /* the raw, unescaped subject - probably won't be used, but we'll
 ** provide it anyway
  */
 snprintf(name, MAX_TMP_NAME, "message.%d.subject", i);
 cs_set_value(name, ptr->topic_head->data.info.subject);
    
    
 /* the html escaped subject */
  snprintf(name, MAX_TMP_NAME, "message.%d.escaped_subject", i);
  cs_html_escape_string(ptr->topic_head->data.info.subject, &escaped_subject);
  cs_set_value(name, escaped_subject);
  if(escaped_subject)
       free(escaped_subject);     



  /* real name of the person who sent the message */
  snprintf(name, MAX_TMP_NAME, "message.%d.sender", i);
  cs_set_value(name, ptr->topic_head->data.info.sender_realname);



  /* date/time message was sent */
  if ( !((common.grp == ANONYMOUS_DISCUSSION) && HIDE_ANONYMOUS_TIMES))	/* see custom.h */
  {    strftime (timestring, MAX_TIMESTRING, DOW_DATE_FORMAT,
	      localtime (&(ptr->topic_head->data.info.time_sent)));
  
       snprintf(name, MAX_TMP_NAME, "message.%d.time_sent", i);
       cs_set_value(name, timestring);
  }


  /* 'raw' status information - this integer won't be too useful, but we'll
  ** provide it anyway
   */
  basic_status =  BASIC_STATUS(ptr->topic_head->data.status);  /* BASIC_STATUS #defined in global.h */
  snprintf(name, MAX_TMP_NAME, "message.%d.raw_status", i);
  cs_set_int_value(name, basic_status);  
 
  

  snprintf(name, MAX_TMP_NAME, "message.%d.basic_status", i);
  switch(basic_status)
   {
     case NORMAL:    	    cs_set_value(name,"NORMAL");
                            break;
                     
     case DELETED:   	    cs_set_value(name, "DELETED");    /* should never happen */
                            break;
  
     case TEACHER_HIDDEN:   cs_set_value(name, "TEACHER_HIDDEN");
                            break;

     case TIMED_RELEASE :   cs_set_value(name, "TIMED_RELEASE");
                            /* there should also be a release time */
                            snprintf(name, MAX_TMP_NAME, "message.%d.release_time", i);
                            strftime (timestring, MAX_TIMESTRING, DOW_DATE_TIME_FORMAT,localtime (&(ptr->topic_head->data.release_time)) );
                            cs_set_value(name,timestring);           

                            /* the unrelease time is optional */           
                            if(ptr->topic_head->data.unrelease_time)
                              {
                                strftime (timestring, MAX_TIMESTRING, DOW_DATE_TIME_FORMAT,
                                                          localtime (&(ptr->topic_head->data.unrelease_time)) );
                                snprintf(name, MAX_TMP_NAME, "message.%d.unrelease_time", i);
                                cs_set_value(name, timestring);  
                               } 
                            break;
                            
     case READ_ONLY:        cs_set_value(name, "READ_ONLY");
                            break;

     default:               cs_set_value(name, "UNDEFINED");
                            break;
  }                             
                                                 
 


 i++; 

#undef MAX_TMP_NAME

}




void
process_all_topics ( SESSION *user)
{
  TOPIC_NODE *ptr;
  time_t now;
  char teamstring[10];
  char timestring[MAX_TIMESTRING + 1];
    
  if(common.is_fac_teamteach)
    snprintf(teamstring,10,"&team=%c", common.team);
  else
    *teamstring = '\0';
      
  
  build_msg_tree(user,common.grp, 0, 1, &now);   /* shared_news_util.c */
  build_topic_list (now);

  strftime (timestring, MAX_TIMESTRING, DOW_DATE_TIME_FORMAT,
	    localtime (&now));

  
  if (topic_head)
    {
      
      for (ptr =  topic_head; ptr; ptr =  ptr->next)
              set_message_data (ptr,now,teamstring);
      free_topic_list ();
    }			

  free_msg_tree(tree_head);  /* shared_news_util.c */
}








   




static void
display_topics ( CONFIG_STRUCT *conf, SESSION *user)
{


  get_fromstring ();
  common.no_topic_type = !group_uses_topic (common.grp);	/* shared_news_util.c */

  /* print the header info */
  cs_set_course_info(conf);
  cs_set_current_time(); 

  set_general_values (conf, user);
  process_all_topics (user);

}





int
main (void)
{
  char tmp[10];
  SESSION user;
  CONFIG_STRUCT conf;		

  cs_cgi_init();

  read_topic_parameters ();
  read_configuration_file (common.course, &conf);	/* shared_util.c */
  validate_key (common.key, &user, &conf);		/* shared_util.c */
 
  if(user.group != FACULTY)
     cs_critical_error(ERR_REQUEST_DENIED, "");
     
  common.is_fac_assignments = (user.group == FACULTY) && (common.grp == ASSIGNMENTS);
  if ((user.group == FACULTY) && (common.grp == TEAM_TEACH))
    {
      common.is_fac_teamteach = 1;
      cs_get_required_parameter ("team", tmp, 5);	
      common.team = *tmp;   				/* switch this teacher's team to that supplied on the command line */
      user.team = common.team;
    }
  else
    {
      common.is_fac_teamteach = 0;
      common.team = NOTEAM;
    }


  set_discussion_names (conf.course_path, user.username, common.grp);	/* shared_news_util.c */
  display_topics (&conf, &user);
  cs_cgi_display("news_manage_topic_list", 1);
  cs_cgi_destroy();
  return 0;
}



