#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "../global.h"

#include "shared_cs_util.h"
#include "shared_file_util.h"
#include "shared_bb_examview.h"

static void
print_head(const char *title, FILE *fp)
{
   fprintf(fp, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
              "<hotpot-jbc-file>\n"
   "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n"
   "<rdf:Description rdf:about=\"\">\n"
   "<dc:creator>UNREGISTERED</dc:creator>\n"
   "<dc:title>This is the title</dc:title>\n"
   " </rdf:Description>\n"
   " </rdf:RDF><version>6</version>\n"
   "<data>\n");
   fprintf(fp, "<title>%s</title>\n", title);
   fprintf(fp, "<reading>\n"
          "<include-reading>0</include-reading>\n"
          "<include-timer>0</include-timer>\n"
          " <time-limit>1</time-limit>\n"
          "    <internal-reading>1</internal-reading>\n"
          "<path-to-reading></path-to-reading>\n"
          "   <reading-title></reading-title>\n"
          "    <reading-text></reading-text>\n"
          "</reading>\n"
          "<questions>\n");
}

static void
print_question(XML_QUESTION *quest, FILE *fp)
{
    int i;
    if(strcmp(quest->type, "tf") ==0 || strcmp(quest->type, "mc") ==0 || strcmp(quest->type, "bk") == 0)
   {
        fprintf(fp, "<question-record>\n");
        fprintf(fp, "<must-select-all>0</must-select-all>\n");

      fprintf(fp, "  <question><![CDATA[ %s ]]></question>\n", quest->quest);
      if(strcmp(quest->type, "tf") ==0 || strcmp(quest->type, "mc") ==0)
         fprintf(fp, "  <question-type>1</question-type>\n");
     else
         fprintf(fp, "  <question-type>2</question-type>\n");

     for(i =0; i<MAX_CHOICE; i++)
     {
          if(quest->choices[i].one_choice)
          {
           fprintf(fp, "     <answer>\n");
           fprintf(fp, "       <text><![CDATA[%s ]]></text>\n",quest->choices[i].one_choice);

           if(strcmp(quest->type, "bk") ==0)
              fprintf(fp, "       <correct><![CDATA[%d ]]></correct>\n",1);
	   else
	      fprintf(fp, "       <correct><![CDATA[%d ]]></correct>\n",quest->choices[i].correct);
	   fprintf(fp, "       <feedback></feedback>\n");
	   fprintf(fp, "     </answer>\n");
        }
    }

     fprintf(fp, "</question-record>\n");
     }
}


static void
print_footer(FILE *fp)
{
   fprintf(fp, "</questions>\n"
	  " </data>\n"
	  " <hotpot-config-file>\n"
	  " <jbc>\n"
	  " <exercise-subtitle>Multiple-choice exercise</exercise-subtitle>\n"
	  " <instructions>Choose the correct answer for each question.</instructions>\n"
	  " <guess-correct>Correct!</guess-correct>\n"
	  " <guess-incorrect>Sorry! Try again.</guess-incorrect>\n"
	  " <next-ex-url>nextpage.htm</next-ex-url>\n"
	  " <send-email>0</send-email>\n"
	  " <top-frame-size>25</top-frame-size><top-frame-units>%%</top-frame-units>\n"
	  " <continuous-scoring>1</continuous-scoring>\n"
	  " <shuffle-questions>0</shuffle-questions>\n"
	  " <shuffle-answers>0</shuffle-answers>\n"
	  " <show-one-by-one>1</show-one-by-one>\n"
	  " <show-limited-questions>0</show-limited-questions>\n"
	  " <questions-to-show>3</questions-to-show>\n"
	  " <separate-javascript-file>0</separate-javascript-file>\n"
	  " </jbc>\n"
	  " <global>\n"
	  " <your-score-is>Your score is </your-score-is>\n"
	  "<correct-indicator>:-)</correct-indicator>\n"
	  " <incorrect-indicator>X</incorrect-indicator>\n"
	  " <correct-first-time>Questions answered correctly first time: </correct-first-time>\n"
	  " <remaining-time>Remaining time:</remaining-time>\n"
	  " <start-reading>Start reading</start-reading>\n"
	  " <show-reading-again>Show reading again</show-reading-again>\n"
	  " <times-up>Your time is over!</times-up>\n"
	  " <click-to-show>Click on the button to see the reading.</click-to-show>\n"
	  " <next-ex-caption>=&gt;</next-ex-caption>\n"
	  " <back-caption>&lt;=</back-caption>\n"
	  " <contents-caption>Index</contents-caption>\n"
	  " <include-next-ex>1</include-next-ex>\n"
	  " <include-contents>1</include-contents>\n"
	  " <include-back>1</include-back>\n"
	  " <contents-url>index.htm</contents-url>\n"
	  " <graphic-url></graphic-url>\n"
	  " <font-face>Geneva,Arial</font-face>\n"
	  " <page-bg-color>#ffffff</page-bg-color>\n"
	  " <title-color>#000033</title-color>\n"
	  " <ex-bg-color>#bbbbee</ex-bg-color>\n"
	  " <text-color>#000000</text-color>\n"
	  " <link-color>#0000ff</link-color>\n"
	  " <vlink-color>#0000cc</vlink-color>\n"
	  " <nav-bar-color>#000066</nav-bar-color>\n"
	  " <formmail-url>http://your.server.address/cgi-bin/FormMail.pl</formmail-url>\n"
	  " <email>you@yourplace.com</email>\n"
	  " <name-please>Please enter your name:</name-please>\n"
	  " <correct-first-time>Questions answered correctly first time: </correct-first-time>\n"
	  " <check-caption>Check</check-caption>\n"
	  " <ok-caption>OK</ok-caption>\n"
	  " </global>\n"
	  " </hotpot-config-file>\n"
	  " </hotpot-jbc-file>\n");
}

static void
write_cgi_file (FILE *infp, off_t size, char *filepath)
{

#define CHUNKSIZE 2048
  FILE  *outfp;
  int bytes_read;
  int bytes_left;
  char buffer[CHUNKSIZE];
  int fd;


  snprintf(filepath, MAX_PATH +1, "%s/CGI_DATA_xml_XXXXXX", "../tmp");
  fd = mkstemp (filepath);
   if(fd == -1)
       cs_critical_error (ERR_MKSTEMP_FAILED, "");
   close(fd);
   change_mkstemp_permission(filepath);   /*shared_file_util.c */

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

    bytes_left = 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, "");

	  bytes_left -= bytes_read;
	  if (fwrite (buffer, bytes_read, 1, outfp) != 1)
	       cs_critical_error (ERR_FWRITE_FAILED, filepath);

     }
    fclose (outfp);
#undef CHUNKSIZE
}

static void
get_orig_fname (const char *full_orig_name, char *orig_fname)
{

  char *temp_fname;
  char *ptr;
  int chars_to_copy;
  char *extension;
   
  temp_fname = (char *) malloc(strlen(full_orig_name) + 1);
  if(!temp_fname)
      cs_critical_error(ERR_MALLOC_FAILED, "");
      

 /* Depending on the browser and the OS, full_orig_name might contain
 ** paths that are separated by backslashes, by forward slashes, or 
 ** no path info at all.  We need to get just the filename...
 **/

  ptr = strrchr (full_orig_name, '\\');   /* look for a backslash from the end of the string */
  if (ptr)                                /* found, then ... */
    strcpy (temp_fname, ptr + 1);         /* filename is to right of the backslash */
  else                                    /* no backslash found */
    {
      ptr = strrchr (full_orig_name, '/');    /* look for a forward slash */
      if (ptr)			              /* found, then ... */
	strcpy (temp_fname, ptr + 1);         /* filename is to right of forward slash */
      else                                    /* no backslash or forward slashes found */
	strcpy (temp_fname, full_orig_name);  /* entire string is the filename */
    }
 
 
  /* If the filename is longer than allowed, we must shorten it
  ** If possible, we'll preserve the file's extension 
  **/
 
  if(strlen(temp_fname) > MAX_FILENAME)   
   {
     extension = strrchr(temp_fname, '.');   /* find start of file extension */
     
     /* If no file extension found, or the file extension is as large as we allow
     ** for an entire filename, simply truncate the filename 
     **/
     if(!extension  || (extension && (strlen(extension) >= MAX_FILENAME) )) 
       {
        *(temp_fname + MAX_FILENAME) = '\0';  /*simply shorten the filename */
        strncpy(orig_fname, temp_fname, MAX_FILENAME + 1);
       } 
     else   /* preserve the file extension, but truncate the rest of the file */
       {
        chars_to_copy = MAX_FILENAME - strlen(extension);
        *(temp_fname + chars_to_copy) = '\0';
        snprintf(orig_fname,MAX_FILENAME + 1, "%s%s", temp_fname, extension);
       }
   }
  else    /** filename was not too long */
      strncpy(orig_fname, temp_fname, MAX_FILENAME + 1);
      
      
  /* make double-sure the file is truncated ! */    
  *(orig_fname + MAX_FILENAME) = '\0';
            
  free(temp_fname);
}              

void
get_xml_file( char *xml_org_file, char *unique_fname)
{
    FILE *fp;
    char path[MAX_PATH +1];
    struct stat buf;

    cs_get_required_parameter("xml_file", path, MAX_PATH +1);
    fp = cgi_filehandle(global_cgi, "xml_file");
    if(fstat(fileno(fp), &buf))
	  cs_critical_error(ERR_STAT_FAILED, path);
    if(buf.st_size == 0)
	  cs_critical_error(ERR_EMPTY_FILE, path);
    get_orig_fname (path, xml_org_file);
    write_cgi_file(fp, buf.st_size, unique_fname);
}

void
xml_to_jbc ( QUEST_LIST *list, char *jbc_file)
{

  FILE *fp;
  int fd;

  snprintf(jbc_file, MAX_PATH +1, "%s/CGI_DATA_jbc_XXXXXX", "../tmp");
   fd = mkstemp (jbc_file);
   if(fd == -1)
       cs_critical_error (ERR_MKSTEMP_FAILED,"" );
   close(fd);
   change_mkstemp_permission(jbc_file);   /*shared_file_util.c */

   fp = fopen (jbc_file, "w");
   if(!fp)
     cs_critical_error (ERR_MKSTEMP_FAILED, "");
   print_head(list->title, fp);
   for(list->current = list->head; list->current; list->current = list->current->next)
         print_question(list->current, fp);
    print_footer(fp);
    fclose(fp);
}

void
send_jbc_file(const char *jbc_file, const char *org_file)
{
     char jbc_org_filename[MAX_PATH +1];
     char *ptr;
     FILE *fp;
     struct stat buf;
     char *buffer;
    
     ptr = strchr(org_file, '.');
     if(ptr)
	  *ptr = '\0';
     snprintf(jbc_org_filename, MAX_PATH +1, "%s.jbc", org_file);

     if(stat(jbc_file, &buf))
	  cs_critical_error (ERR_STAT_FAILED, "");
      buffer = (char *) malloc( (buf.st_size +1) * sizeof(char));
      if(!buffer)
           cs_critical_error (ERR_MALLOC_FAILED, "");

      fp = fopen(jbc_file, "r");
      if(!fp)
          cs_critical_error(ERR_FOPEN_READ_FAILED, "");
       if (fread (buffer, buf.st_size, 1, fp) != 1)
          cs_critical_error (ERR_FREAD_FAILED, "");
      fclose(fp);
      printf ("Content-type:application/octet-stream\n");
      printf ("Content-disposition: attachment; filename=\"%s\"\n", jbc_org_filename);
      printf("Content-length: %ld\n\n", (long)buf.st_size);
      if(fwrite(buffer, buf.st_size, 1, stdout) != 1)
          cs_critical_error (ERR_FWRITE_FAILED, "");
      free(buffer);
      unlink(jbc_file);
}

void
dat_to_jbc ( QUEST_LIST *list, char *jbc_file)
{

  FILE *fp;

  fp = fopen (jbc_file, "w");
  if(!fp)
     cs_critical_error (ERR_FOPEN_WRITE_FAILED, jbc_file);
  print_head(list->title, fp);
  for(list->current = list->head; list->current; list->current = list->current->next)
              print_question(list->current, fp);
  print_footer(fp);
  fclose(fp);
}

XML_QUESTION *
initialize()
{
   XML_QUESTION *ptr;
   int i;

   ptr = (XML_QUESTION*)malloc(sizeof(XML_QUESTION));
   ptr->quest = 0;
   ptr->feedback =0;
   ptr->next =0;
   for(i = 0; i < MAX_CHOICE; i++)
   {
       ptr->choices[i].one_choice = 0;
       ptr->choices[i].id = 0;
       ptr->choices[i].correct =0;
   }
   return ptr;
}

void free_xml_data_list(QUEST_LIST *list)
{
  XML_QUESTION *ptr;
  int i;

   list->current = list->head;
   while(list->current)
  {
      ptr = list->current;
      if(ptr->quest)
           free(ptr->quest);
      if(ptr->feedback)
      free(ptr->feedback);
     for(i =0; i<MAX_CHOICE; i++)
     {
          if(ptr->choices[i].one_choice)
             free(ptr->choices[i].one_choice);
          if(ptr->choices[i].id)
               free(ptr->choices[i].id);

      }
      list->current = list->current->next;
      free(ptr);
  }
  if(list->title)
     free(list->title);
   free(list);
}




