/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  backendn-scrn.c defines the notes screen output backend of refdbd
  markus@mhoenicka.de 2003-10-14

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, see <http://www.gnu.org/licenses/>

  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

#include <string.h>
#include <stdio.h>
#include <syslog.h> /* for definitions of log message priorities */
#include <time.h>
#include <dbi/dbi.h>

#include "refdb.h"
#include "backend.h"
#include "backendn-html.h"
#include "strfncs.h"
#include "linklist.h"
#include "refdbd.h"
#include "dbfncs.h"
#include "connect.h"

/* some globals */
extern int n_log_level; /* numeric version of log_level */

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  prepare_render_note_html(): writes a header for the html output of a
                         notes query

  int prepare_render_note_html returns 0 if successful, >0 if failed

  struct renderinfo* ptr_rendinfo ptr to a structure with the info
                             how the note should be rendered

 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int prepare_render_note_html(struct renderinfo* ptr_rendinfo) {
  char* new_ref;
  char* header;

  if ((header = assemble_header(ptr_rendinfo)) == NULL) {
    return 801;
  }

  if ((new_ref = mstrcpy(*(ptr_rendinfo->ptr_ref), header, ptr_rendinfo->ptr_ref_len)) == NULL) {
    free(header);
    LOG_PRINT(LOG_CRIT, get_status_msg(801));
    return 801;
  }
  else {
    *(ptr_rendinfo->ptr_ref) = new_ref;
    free(header);
  }
  return 0;
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  finish_render_note_html(): writes a footer for the html output of
                             a notes query

  int finish_render_note_html returns ptr to the buffer if successful,
                        NULL if failed

  struct renderinfo* ptr_rendinfo ptr to a structure with the info
                             how the reference should be rendered

 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int finish_render_note_html(struct renderinfo* ptr_rendinfo) {
  char* new_ref;

  if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</body>\n</html>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
    LOG_PRINT(LOG_WARNING, get_status_msg(801));
    return 801;
  }
  else {
    *(ptr_rendinfo->ptr_ref) = new_ref;
  }
  return 0;
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  render_note_html() renders a note for html display

  int render_note_html returns ptr to the buffer if successful,
                     NULL if failed

  struct renderinfo* ptr_rendinfo ptr to a structure with the info
                             how the reference should be rendered

  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int render_note_html(struct renderinfo* ptr_rendinfo) {
  char id[32] = "";
  char date_buffer[256];
  char hr_buffer[10];
  char linktype[4][11] = {"reference", "keyword", "author", "periodical"};
  const char* citem;
  char* item;
  char* new_ref;
  char* entitize_buf;
  dbi_conn conn;

  if (ptr_rendinfo->ref_format == REFXHTML) {
    strcpy(hr_buffer, "<hr />\n");
  }
  else {
    strcpy(hr_buffer, "<hr>\n");
  }

  conn = dbi_result_get_conn(ptr_rendinfo->dbires);

  /*----------------------------------------------------------------*/
  /* ID */
  get_refdb_note_id(ptr_rendinfo->dbires, id);

  if (*id) {
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<div class=\"record\">\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<h2 class='ID'>Note ID:", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    /* ID */
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), id, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</h2>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }
  else {
    LOG_PRINT(LOG_WARNING, get_status_msg(234));
    return 234; /* this is bad and will hopefully never happen */
  }

  /*----------------------------------------------------------------*/
  /* date */
  if (get_refdb_note_date(ptr_rendinfo->dbires, date_buffer, 0) != NULL) {
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<p class=\'date\'>Date: ", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    /* date */
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), date_buffer, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</p>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }

  /*----------------------------------------------------------------*/
  /* note key */
  citem = get_refdb_note_key(ptr_rendinfo->dbires);
  if (citem && *citem) {
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<p class=\'citekey\'>Key: ", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), (char*)citem, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</p>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }

  /*----------------------------------------------------------------*/
  /* note title */
  item = get_refdb_note_title_copy(ptr_rendinfo->dbires);
  if (item != NULL) {
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<p class=\'title\'>", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    if (sgml_entitize(&item, ptr_rendinfo->ref_format) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      free(item);
      return 801;
    }
      
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), (char*)item, ptr_rendinfo->ptr_ref_len, 0)) == NULL) { /* title */
      free(item);
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    free(item);

    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</p>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }

  /*----------------------------------------------------------------*/
  /* the note proper */
  item = get_refdb_note_content_copy(ptr_rendinfo->dbires);
  if (item != NULL) {
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<p class=\'note\'>", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    if (sgml_entitize(&item, ptr_rendinfo->ref_format) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      free(item);
      return 801;
    }
      
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), (char*)item, ptr_rendinfo->ptr_ref_len, 0)) == NULL) { /* note proper */
      free(item);
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    free(item);

    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</p>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }

  /*----------------------------------------------------------------*/
  /* links */
  
  if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "NL") != NULL
      || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    int i;
    dbi_result dbires;

    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<p class=\'notexhead\'>Note is attached to:</p>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) { /* note proper */
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
    
    /* loop over reference, keyword, author, periodical links */
    for (i = 0; i < 4; i++) {
      int mode = i;
      dbires = request_links(conn, my_dbi_result_get_idval(ptr_rendinfo->dbires, "note_id"), i);
      if (dbires == NULL) {
	return 234;
      }

      /* fetch all links of this type and note */
      while ((citem = get_link(dbires, &mode)) != NULL) {
	if (i == 3) { /* periodical */
	  if (!mode) { /* full name */
	    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<p class=\'notex\'>Periodical full name: ", ptr_rendinfo->ptr_ref_len, 0)) == NULL) { /* note proper */
	      free(item);
	      LOG_PRINT(LOG_CRIT, get_status_msg(801));
	      return 801;
	    }
	    else {
	      *(ptr_rendinfo->ptr_ref) = new_ref;
	    }
	  }
	  else if (mode == 1) { /* abbrev */
	    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<p class=\'notex\'>Periodical abbreviation: ", ptr_rendinfo->ptr_ref_len, 0)) == NULL) { /* note proper */
	      free(item);
	      LOG_PRINT(LOG_CRIT, get_status_msg(801));
	      return 801;
	    }
	    else {
	      *(ptr_rendinfo->ptr_ref) = new_ref;
	    }
	  }
	  else if (mode == 2) { /* custabbrev 1 */
	    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<p class=\'notex\'>Periodical custom abbreviation 1: ", ptr_rendinfo->ptr_ref_len, 0)) == NULL) { /* note proper */
	      free(item);
	      LOG_PRINT(LOG_CRIT, get_status_msg(801));
	      return 801;
	    }
	    else {
	      *(ptr_rendinfo->ptr_ref) = new_ref;
	    }
	  }
	  else if (mode == 3) { /* custabbrev 2 */
	    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<p class=\'notex\'>Periodical custom abbreviation 2: ", ptr_rendinfo->ptr_ref_len, 0)) == NULL) { /* note proper */
	      free(item);
	      LOG_PRINT(LOG_CRIT, get_status_msg(801));
	      return 801;
	    }
	    else {
	      *(ptr_rendinfo->ptr_ref) = new_ref;
	    }
	  }
	}
	else {
	  /* reuse date_buffer */
	  sprintf(date_buffer, "<p class=\'notex\'>%s: ", linktype[i]);
	  if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), date_buffer, ptr_rendinfo->ptr_ref_len, 0)) == NULL) { /* note proper */
	    free(item);
	    LOG_PRINT(LOG_CRIT, get_status_msg(801));
	    return 801;
	  }
	  else {
	    *(ptr_rendinfo->ptr_ref) = new_ref;
	  }
	}

	if ((entitize_buf = strdup(citem)) != NULL
	    && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  return 801;
	}
      
	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), entitize_buf, ptr_rendinfo->ptr_ref_len, 0)) == NULL) { /* note proper */
	  free(item);
	  free(entitize_buf);
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}

	free(entitize_buf);

	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</p>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) { /* note proper */
	  free(item);
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}
      }
      clean_request(dbires);
    } /* end for */
  }

  /*----------------------------------------------------------------*/
  /* ulink */
  if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "UR") != NULL
      || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    int i;
    char *entitize_string;
    char keytype[5][10] = {"URL", "PDF", "FULLTEXT", "RELATED", "IMAGE"};
    char buffer[64];
    dbi_result dbires;

    /* loop over all link types */
    for (i=0; i<5;i++) {
      dbires = request_ulinks(conn, my_dbi_result_get_idval(ptr_rendinfo->dbires, "note_id"), 1 /* notes entry */, i /* link type */, 0 /* is_temp */, ptr_rendinfo->username);
      if (dbires == NULL) {
	return 234;
      }

      while ((citem = get_ulink(dbires)) != NULL) {
	sprintf(buffer, "<p class='ur'>%s: <a href=\"", keytype[i]);
	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), buffer, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  clean_request(dbires);
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}

	if (i>0 && i<5) {
	  entitize_string = add_root_to_link(citem, ptr_rendinfo->pdfroot);
	}
	else {
	  entitize_string = strdup(citem);
	}

	if (entitize_string == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  clean_request(dbires);
	  return 801;
	}

	if (sgml_entitize(&entitize_string, ptr_rendinfo->ref_format) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  clean_request(dbires);
	  free(entitize_string);
	  return 801;
	}
      
	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), entitize_string, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  clean_request(dbires);
	  free(entitize_string);
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}

	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "\">", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  clean_request(dbires);
	  free(entitize_string);
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}

	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), entitize_string, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  clean_request(dbires);
	  free(entitize_string);
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}

	free(entitize_string);

	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</a></p>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}
      } /* end while */
      clean_request(dbires);
    } /* end for */
  }

  if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</div>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
    LOG_PRINT(LOG_CRIT, get_status_msg(801));
    return 801;
  }
  else {
    *(ptr_rendinfo->ptr_ref) = new_ref;
  }

/*      printf("%s\n", ref); */
  return 0;
}
