#include <stdio.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_authenticate.h"
#include "manhat-lib/shared_lock.h"
#include "manhat-lib/shared_update_user_info.h"
#include "manhat-lib/shared_person_list.h"
#include "manhat-lib/shared_access.h"
#include "manhat-lib/shared_teamstring.h"


typedef struct user_team
{
   USER_DATA data;
   char new_team;
   struct user_team  *next;
}USER_TEAM;

typedef struct username_team
{
     char username[MAX_USERNAME +1];
     char team;
     struct username_team *next;
}USERNAME_TEAM;

USER_TEAM *
get_user_team_node(const char *team, P_NODE *std_ptr)
{
   USER_TEAM * team_ptr;

      team_ptr = (USER_TEAM *)malloc(sizeof(USER_TEAM));
      if(!team_ptr)
	   cs_critical_error(ERR_MALLOC_FAILED, "");
      strncpy(team_ptr->data.username, std_ptr->data.username, MAX_USERNAME+1);
      strncpy(team_ptr->data.realname, std_ptr->data.realname, MAX_NAME+1);
      strncpy(team_ptr->data.lastname, std_ptr->data.lastname, MAX_NAME+1);
      strncpy(team_ptr->data.password, "x", MAX_PASSWORD+1);
      strncpy(team_ptr->data.id, std_ptr->data.id, MAX_ID+1);
      strncpy(team_ptr->data.alias, std_ptr->data.alias, MAX_NAME+1);
      team_ptr->data.team = std_ptr->data.team;
      team_ptr->data.group = std_ptr->data.group;
      team_ptr->new_team = *team;
      team_ptr->next =0;
      return team_ptr;
}

USER_TEAM *
get_username_team(CONFIG_STRUCT *conf)
{
   char team[4];
   P_NODE *std_head =0, *std_ptr;
   USER_TEAM *head = 0, *team_ptr, *current = 0;
  
   std_head = build_option_person_list(conf);
   for(std_ptr = std_head; std_ptr; std_ptr = std_ptr->next)
   {
      cs_get_required_parameter(std_ptr->data.username,team, 3);
      team_ptr = get_user_team_node(team, std_ptr);
      if(!head)
          head = team_ptr;
      else
        current->next = team_ptr;
      current = team_ptr; 
   }

   free_option_person_list (std_head);
   return head;
}



void
read_parameters (char *course, char *key)
{

  cs_get_required_parameter ("crs", course, MAX_PATH);
  cs_get_required_parameter ("id", key, MAX_KEY);
}



int user_cmp(USER_TEAM *a, USER_TEAM *b)
{
  
  if(a->new_team < b->new_team)
     return -1;
  if(a->new_team > b->new_team)
     return 1;
        
  return username_cmp(&(a->data), &(b->data));   /* shared_authenticate.c */
}
  
      

USER_TEAM *
sort_by_new_team (USER_TEAM *head)
{
  USER_TEAM *q, *tail, *p, *r;
  if (head != NULL)
  {
      tail = head;
      while (tail->next)
      {
          q = tail->next;
          if(user_cmp(q,head) < 0)    // q->new_team < head->new_team) /* shared_authenticate.c */
           {
             tail->next = q->next;
             q->next = head;
             head = q;
           }
         else
         {
           r = head;
           p = r->next;
          while (user_cmp(q,p) > 0 )   //q->new_team >  p->new_team) /* shared_authenticate.c */
          {
              r = p;
              p = r->next;
          }
         if (q == p)
            tail = q;
         else
         {
            tail->next = q->next;
            q->next = p;
           r->next = q;
         }
      }
    }
  }
  return head;
}

     


void free_userteam_list(USER_TEAM  *head)
{
    USER_TEAM  *ptr;
    while (head)
    {
      ptr = head->next;
      free (head);
      head = ptr;
    }
}





void
update_user_team(USER_TEAM *team_head,  CONFIG_STRUCT *conf, const char *course)
{
	USER_TEAM *team_ptr;
	USER_DATA new_data;

	for(team_ptr = team_head; team_ptr; team_ptr = team_ptr->next)
	{
	  if(team_ptr->data.team != team_ptr->new_team)
	  {
	      strncpy(new_data.username, team_ptr->data.username, MAX_USERNAME +1);
	      strncpy(new_data.realname, team_ptr->data.realname, MAX_NAME +1);
	      strncpy(new_data.password, "x", MAX_PASSWORD +1);
	      strncpy(new_data.id, team_ptr->data.id, MAX_ID +1);
	      new_data.group = team_ptr->data.group;
	      new_data.team =  team_ptr->new_team;
	      strncpy(new_data.alias, team_ptr->data.alias, MAX_NAME +1);

	      mark_passwd_file (team_ptr->data.username, conf);  /* shared_update_user_info.c */
	      update_passwd (&new_data, conf);                   /* shared_update_user_info.c */
	      update_course_key(&new_data, course);              /* shared_update_user_info.c */
	  }
       }
}
	

void
set_result_data (USER_TEAM *team_head, CONFIG_STRUCT *conf,  const char *crs, const char *key)
{
  #define MAX_TMP_NAME 30
  USER_TEAM *person_ptr;
  char name[MAX_TMP_NAME];
  char url[MAX_PATH +1];
  int i =0;

  snprintf (url, MAX_PATH +1, "%s?crs=%s&amp;id=%s", "admin_main_menu", crs, key);
  cs_set_value("back_url", url);
  cs_set_course_info(conf);
  cs_set_current_time();

  for (person_ptr = team_head; person_ptr; person_ptr = person_ptr->next)
  {
       snprintf(name, MAX_TMP_NAME, "person.%d.username", i);
       cs_set_value(name, person_ptr->data.username); 
       snprintf(name, MAX_TMP_NAME, "person.%d.realname", i);
       cs_set_value(name, person_ptr->data.realname); 
       snprintf(name, MAX_TMP_NAME, "person.%d.alias", i);
       cs_set_value(name, person_ptr->data.alias); 
       snprintf(name, MAX_TMP_NAME, "person.%d.id", i);
       cs_set_value(name, person_ptr->data.id); 
       snprintf(name, MAX_TMP_NAME, "person.%d.group", i);
       cs_set_value(name, person_ptr->data.group == FACULTY?"faculty":"student"); 
       snprintf(name, MAX_TMP_NAME, "person.%d.new_team", i);
       get_team_name(person_ptr->new_team, url);
       cs_set_value(name, url);
       if(person_ptr->new_team != person_ptr->data.team)
       {
          snprintf(name, MAX_TMP_NAME, "person.%d.old_team", i);
          get_team_name(person_ptr->data.team, url);
          cs_set_value(name, url);
       }
       i++;
  }
  cs_set_int_value("num_people", i);
  cs_set_int_value("changed", 1);
}


int
main ()
{
  char course[MAX_PATH + 1];	/* from crs=? command line */
  char key[MAX_KEY + 1];	/* from id=? command line */
  SESSION user;
  CONFIG_STRUCT conf;		/* the configuration read from config file */
  USER_TEAM *team_head;

  cs_cgi_init();

  read_parameters (course, key);
  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();                 /* shared_access.c */

  if ((user.group == FACULTY) || (user.group == ADMIN))
  {
      team_head = get_username_team(&conf);
      update_user_team(team_head,  &conf, course);
      team_head = sort_by_new_team(team_head);
      set_result_data (team_head, &conf,  course, key);
      free_userteam_list(team_head);
  }
  else
    cs_critical_error (ERR_REQUEST_DENIED, "");

 #ifdef HIDE_MANHATTAN_USERNAMES
   cs_set_int_value("hide_manhattan_username", 1);
  #endif
    
  /* this program shares a cs file with admin_assign_team_form.c */  
  cs_cgi_display("admin_assign_team_form", 1);
  cs_cgi_destroy();
  return 0;			/* exit successfully */
}

