#include <stdio.h>
#include <string.h>
#include <sys/stat.h>		/* for stat() */
#include <unistd.h>		/* for unlink() */
#include <ctype.h>

#include <sys/types.h>		/* for exec(), wait() et. al */
#include <sys/wait.h>


#include "global.h"

#include "manhat-lib/shared_util.h"
#include "manhat-lib/shared_super_util.h"
#include "manhat-lib/shared_strtrm.h"
#include "manhat-lib/shared_bio.h"
#include "manhat-lib/shared_news_util.h"
#include "manhat-lib/shared_file_util.h"
#include "manhat-lib/shared_lock.h"
#include "manhat-lib/shared_cs_util.h"
#include "manhat-lib/shared_fold_file.h"
#include "manhat-lib/shared_system_data.h"





/** Course is an optional parameter.  If course is sent,
*** the the user is working within a Manhattan course.
*** Otherwise, they are working from the My Manhattan page.
***/

static void
read_parameters (char *course, char *key, char *username, int *is_admin,
                 char *email, char *website, int *photo)

{
  char tmp[10 + 1];
  

  cs_get_required_parameter ("id", key, MAX_KEY);
  cs_get_required_parameter ("user", username, MAX_USERNAME);
  cs_get_required_parameter ("photo", tmp, 10);
  *photo = atoi(tmp);

  cs_get_optional_parameter("email", email, MAX_URL);
  cs_get_optional_parameter("website", website, MAX_URL);
  cs_get_optional_parameter("crs", course, MAX_PATH);
  cs_get_optional_parameter("admin", tmp, 10);
  if(strlen(tmp))
    *is_admin = 1;
  else
    *is_admin = 0;
  
}


    


static void
write_cgi_bio_file (FILE *infp, const char *filepath)
{

#define CHUNKSIZE 2048
  FILE  *outfp;
  int bytes_read;
  int bytes_left;
  char buffer[CHUNKSIZE];
  struct stat file_stat;

  if(fstat(fileno(infp), &file_stat))
       cs_critical_error(ERR_NO_FILE, "write cgi file failed");
  if(file_stat.st_size ==0)
       cs_critical_error(ERR_NO_FILE, "write cgi file failed");


  outfp = fopen (filepath, "w");
  if (!outfp)
      cs_critical_error (ERR_FOPEN_WRITE_FAILED, filepath);


  bytes_left = file_stat.st_size;
  bytes_read = CHUNKSIZE;
  while (bytes_left)
    {
      if (bytes_left < CHUNKSIZE)
	bytes_read = bytes_left;
      if (fread (buffer, bytes_read, 1, infp) != 1)
	{
	  cs_critical_error (ERR_FREAD_FAILED, "write cgi file failed");
	}
      bytes_left -= bytes_read;
      if (fwrite (buffer, bytes_read, 1, outfp) != 1)
	{
	  cs_critical_error(ERR_FWRITE_FAILED, "write_cgi_file failed");
	}

    }
  fclose (outfp);
#undef CHUNKSIZE

}







static void
run_thumbnailer (const char *bindir)
{

#define MAX_ARG_SIZE 20
#define MAX_DIMENSION 150
#define MAX_QUALITY 90

  char thumbnail_program[MAX_PATH + 1];
  char size_arg[MAX_ARG_SIZE + 1];
  char quality_arg[MAX_ARG_SIZE + 1];
  pid_t pid, status;


  snprintf(thumbnail_program,MAX_PATH + 1, "%s/jpgtn", bindir);
  snprintf(size_arg, MAX_ARG_SIZE + 1, "-s %d", MAX_DIMENSION);
  snprintf(quality_arg, MAX_ARG_SIZE + 1, "-q %d", MAX_QUALITY);  
  
  
  if ((pid = fork ()) < 0)
    cs_critical_error (ERR_CANT_START_NEW_PROCESS, "thum nail function");

  if (pid == 0)
    {				/* child process */
      execl (thumbnail_program, "jpgtn", "-f", "-pthumb.", size_arg, quality_arg, BIO_ORIG_PIC_FNAME, (char *) 0);
      exit (1);		/* this is returned if above execl() fails */
    }
 /*** parent process */
  while (wait (&status) != pid);


#undef MAX_ARG_SIZE
#undef MAX_DIMENSION
#undef MAX_QUALITY
}




static void
replace_photo(const char *bio_dir)
{

  char current_dir[MAX_PATH + 1];
  char path[MAX_PATH + 1];
  char *filename;
  FILE *fp; 
 
  /** was it a *.jpg file? */
  filename = hdf_get_value(global_cgi->hdf, "Query.photofile",  0);
  if(!filename)
     cs_critical_error(ERR_NO_FILE, "empty upload file");

  get_extension(filename,path);    /* shared_news_util.c */ 
  if(strcmp(path,"jpg") && strcmp(path,"jpeg") && strcmp(path,"JPG") && strcmp(path,"JPEG"))
      cs_critical_error(ERR_NOT_JPG_FILE, "");
  fp = cgi_filehandle(global_cgi, "photofile"); 
  if(!fp)
       cs_critical_error(ERR_NO_FILE, "replace_photo()");

 /* write the uploaded file to BIO_ORIG_PIC_FNAME in the bio_dir   */
 snprintf(path, MAX_PATH + 1, "%s/%s", bio_dir, BIO_ORIG_PIC_FNAME);
 
 write_cgi_bio_file(fp,path);     
      
 /* convert uploaded file to thumbnail */     
 
 /* get current directory so we can return */
 if(!getcwd(current_dir, MAX_PATH + 1))
     cs_critical_error(ERR_CANT_GET_CWD, "");
  
 /* make the bio dir the current directory */ 
 if(chdir(bio_dir))
     cs_critical_error(ERR_CHDIR_FAILED, "");
     
//snprintf(command,MAX_PATH + 1, "%s/mkthumb -o -f %d %s", current_dir, MAX_DIMENSION, BIO_ORIG_PIC_FNAME);
//snprintf(command,MAX_PATH + 1, "%s/jpgtn -f -pthumb. -s %d %s", current_dir, MAX_DIMENSION, BIO_ORIG_PIC_FNAME);
 run_thumbnailer(current_dir);
//system(command);
 

if(chdir(current_dir))
     cs_critical_error(ERR_CHDIR_FAILED, "");

 /* delete uploaded file */
 unlink(path);   

}      
      


static void
delete_photo(const char *bio_dir)
{
 char path[MAX_PATH + 1];
 
 snprintf(path, MAX_PATH + 1, "%s/%s", bio_dir, BIO_PIC_FNAME);  
 unlink(path);
}

 
 
 
/** values of photo (passed from bio_edit_form program)
*** 0 - leave untouched
*** 1 - replace photo with file specified
*** 2 - delete photo
**/    
     
         
static
void handle_photo(int photo, const char *bio_dir)
{
    switch(photo)
    {
     case 1: replace_photo(bio_dir);
             break;
     case 2: delete_photo(bio_dir);
             break;
     case 0:  /* same as default - no changes */
     default: break;
    }
}



static
void delete_empty_bio (const char *bio_dir, const char *narrative_path)
{
 char picture_path[MAX_PATH + 1];

 unlink(narrative_path);     
 snprintf(picture_path,MAX_PATH + 1, "%s/%s",bio_dir, BIO_PIC_FNAME);
 if(!file_exists(picture_path))   /* shared_file_util.c */
   rmdir(bio_dir);
}
   



static
void handle_narrative(const char *email, const char *website, const char *bio_dir)
{
 FILE *fp;
 char path[MAX_PATH + 1];
 char *str=0;
 int i;
 char label[BIO_MAX_CUSTOM_LABEL + 1];
 char content[BIO_MAX_CUSTOM_CONTENT + 1];
 char varname[20];
 int content_found = 0;
  
 snprintf(path,MAX_PATH + 1, "%s/%s",bio_dir, BIO_FNAME);
 
 /* first line is email address */
 fp = fopen(path, "w");
 if(!fp)
     cs_critical_error(ERR_FOPEN_WRITE_FAILED, "");
     
 get_exclusive_lock(fileno(fp), 1);   /* shared_lock.c */    
 /* first line is email address */    
 fprintf(fp,"%s\n", email);
 content_found = strlen(email);
 
 /* second line is website */
 if(*website && !strstr(website,"://"))
     fprintf(fp,"http://");
 fprintf(fp, "%s\n",website);
 if(!content_found)
     content_found = strlen(website);
 
 /* get the optional custom entries */
 for(i=1; i<=BIO_MAX_CUSTOM_ELEMENTS; i++)
  {
   snprintf(varname, 20, "label%d", i);
   cs_get_optional_parameter(varname, label, BIO_MAX_CUSTOM_LABEL);  

   snprintf(varname, 20, "content%d", i);
   cs_get_optional_parameter(varname, content, BIO_MAX_CUSTOM_CONTENT);  
   fprintf(fp,"%s\n%s\n", label, content);
   if(!content_found)
       content_found = strlen(label) || strlen(content);
  } 
 
 
  hdf_get_copy(global_cgi->hdf, "Query.narrative", &str, "");
  if(str && strlen(str))
  {
     content_found = 1;
     if((strlen(str) < system_data_int("EDITOR_WIDTH_STANDARD")) || system_data_int("USE_TEXTAREA_HARD_WRAP"))   /* shared_system_data.h */
         fprintf(fp,"%s", str);
     else
     {
       write_folded(fp, str, system_data_int("EDITOR_WIDTH_STANDARD"));     /* shared_fold_file.c */    
     }
     free(str);
  }   
   
  release_lock(fileno(fp));
  fclose(fp);
  
 if(!content_found)
    delete_empty_bio(bio_dir, path);

}



      
        
       


static void
create_bio_dir(const char *bio_dir)
{
 if(!file_exists(bio_dir))
     mkdir (bio_dir, 0770);
}





int
main ()
{
  char course[MAX_PATH + 1];	            /* from crs=? form value */
  char key[MAX_KEY + 1];	            /* from id=? form value */
  char target_username[MAX_USERNAME + 1];   /* from user=? form value */
  int is_admin;                             /* from admin=? form value */
  char email[MAX_URL + 1];                  /* from email=? form value */
  char website[MAX_URL + 1];                /* from website=? form value */
  int photo;                                /* from photo=? radio button form value */
  
  
  SESSION user;
  CONFIG_STRUCT conf;		            /* the configuration read from config file */
  char bio_dir[MAX_PATH + 1];  
   
  cs_cgi_init();  
  read_parameters (course, key, target_username,&is_admin, email, website, &photo);
  
  

  /* If a course was provided on the form value, read its configuration file.
  ** Set whether or not we're dealing with a standalone course
  **/

  if(*course)
     read_configuration_file(course, &conf);
     

 /* validate the appropriate key */
 if(is_admin)
  {
   if(!*course)
       validate_super_key(key, &user);     /* shared_super_util.c */
   else
       validate_key (key, &user, &conf);	/* shared_util.c */
  }
 else if(!*course)
    validate_server_key(key, &user);       /* shared_util.c */
 else
    validate_key (key, &user, &conf);	/* shared_util.c */

 if(!bio_edit_allowed(&user,target_username, course, &conf))  /* shared_bio.c */
      cs_critical_error (ERR_REQUEST_DENIED, "");

  /* bio info is either stored in ../users/x/username/bio or, for standalone courses in
  ** course_dir/people/username/bio
  */     
  get_bio_dir(course, &conf, target_username, bio_dir);       /* shared_bio.c */

  /** try to create the bio directory if it doesn't already exist **/
  create_bio_dir(bio_dir);
    
  handle_photo(photo, bio_dir);
  handle_narrative(email, website,bio_dir);
  
  /* return to bio_view page */

  printf("Location: %s?id=%s&user=%s", "bio_view",key,target_username); 

  if(is_admin)
      printf("&admin=1");
  if(*course)
       printf("&crs=%s",course);
  printf("&edit=1\n\n");
  cs_cgi_destroy();
  return 0;			/* exit successfully */

}

