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

#include "global.h"

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


typedef struct normal_node
{
 MSG_TREE_NODE *msg_ptr;
 struct normal_node *next;
} NORMAL_NODE;

NORMAL_NODE *normal_head = 0;
 

static void
read_parameters (char *course, char *key, long *offset, int *topic)
{
  char astring[80];


  cs_get_required_parameter ("crs", course, MAX_PATH);	/* shared_cgi_util.c */
  cs_get_required_parameter ("id", key, MAX_KEY);	/* shared_cgi_util.c */

  cs_get_required_parameter ("loc", astring, 79);	/* shared_cgi_util.c */
  *offset = atol (astring);

  cs_get_required_parameter ("topic", astring, 79);	/* shared_cgi_util.c */
  *topic = atoi (astring);
  
}


static void
add_to_normal_list(MSG_TREE_NODE *msg_ptr)
{
 static NORMAL_NODE *last = 0;
 
 if(!normal_head)
  {
   normal_head = (NORMAL_NODE *) malloc(sizeof(NORMAL_NODE));
   if(!normal_head)
     cs_critical_error(ERR_MALLOC_FAILED, "");
   last=normal_head;
  }
 else
  {
   last->next = (NORMAL_NODE *) malloc(sizeof(NORMAL_NODE));
   if(!last->next)
     cs_critical_error(ERR_MALLOC_FAILED, "");
   last = last->next;
  }
  
  last->msg_ptr = msg_ptr;
  last->next = (NORMAL_NODE *) 0;
}


static void free_normal_list()
{
 NORMAL_NODE *ptr;
 
 while(normal_head)
  {
   ptr = normal_head;
   normal_head = normal_head->next;
   free(ptr);
  }          
}



void build_normal_list(MSG_TREE_NODE *root)
{	
 if(!root)
	 return;
 if(BASIC_STATUS(root->data.status) == TEACHER_HIDDEN)
     {
      root->data.status = NORMAL;
      add_to_normal_list(root);
     } 
      
 build_normal_list(root->next);
 build_normal_list(root->reply);
}

static void
write_normal_list()
{
 FILE *fp;
 int fd;
 NORMAL_NODE *ptr;
 char inbox_fname[MAX_PATH + 1];
 
 if(normal_head)
  {
   snprintf(inbox_fname,MAX_PATH + 1,"%s%s",central_discussion_path,INBOX_FNAME);
   fp = fopen(inbox_fname, "r+");
   if(!fp)
     cs_critical_error(ERR_FOPEN_READ_FAILED, "");
   fd = fileno(fp);
   get_exclusive_lock(fd,1);  /* shared_lock.c */
 
   for(ptr = normal_head; ptr; ptr = ptr->next)
    {
     if(fseek(fp,ptr->msg_ptr->offset,SEEK_SET))
       cs_critical_error(ERR_FSEEK_FAILED, "");
     if(fwrite(&(ptr->msg_ptr->data), sizeof(CENTRAL_INBOX_RECORD), 1, fp) != 1)
       cs_critical_error(ERR_FWRITE_FAILED, "");  
    }   
    
    release_lock(fd);
    fclose(fp);
  }
} 
 
  
      

static void
unhide_teacher_hidden(SESSION *user, const char *course, int topic, long offset)
{
 MSG_TREE_NODE *msg_ptr, *topic_ptr;
 int msg_count;
 time_t current_time;

 build_one_topic_tree(user, ASSIGNMENTS, offset, &msg_ptr, &topic_ptr, 
                                                 &msg_count, 0, 1, &current_time);  /* shared_news_util.c */
 if(!msg_ptr || !tree_head || !topic_ptr)
   cs_critical_error(ERR_CANT_FIND_THIS_OFFSET, "");

  build_normal_list(tree_head->reply);
  write_normal_list();
  free_msg_tree(tree_head); /*shared_news_util.c */
  free_normal_list();
}





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 topic;                    /* from topic=? command line */

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

  cs_cgi_init();

  read_parameters (course, key, &offset, &topic);

  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();


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

  set_discussion_names (conf.course_path, user.username, ASSIGNMENTS);	/* shared_news_util.c */
  unhide_teacher_hidden(&user, course,topic,offset);
    
  printf("Location: %s?crs=%s&id=%s&loc=%ld&topic=%d\n\n",  "assign_fac_expand", course, key, offset, topic);
  cs_cgi_destroy();
  return 0;
}

