#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>

#include "xregal.h"
#include "moviedb.h"
#include "printname.h"
#include "dbutils.h"
#include "utility.h"
#include "filmbuf.h"

struct BioInfo {
	char *key;
	char *heading;
	Boolean wrapped;
	Boolean bulleted;
	};

struct BioInfo bio_info[] = {
    { "NM", "Industry Name", False, False },
    { "RN", "Real Name", True, False },
    { "NK", "Nick-Name", True, False },
    { "DB", "Born", True, False }, 	/* <Date of Birth>, <Place of Birth> */
    { "DD", "Died", True, False }, 	/* <Date of Death>, <Cause of death> */
    { "HT", "Height", False, False },
    { "BG", "Biography", True, False },
    { "BY", "Biography by", False, False }, /* <Real Name> followed by mail name */
    { "BO", "Available Biographies", True, True },
    { "BT", "Biographical Films", True, True },
    { "OW", "Other Works", True, True },
    { "GA", "Guest Appearances", True, True },
    { "TR", "General Trivia", True, True },
    { "QU", "Personal Quotes", True, True },
    { "WN", "Where Now", True, True },
    { "AG", "Agent's Address", False, True },
    { "SP", "Married", True, True },
    { "TM", "Trade Mark", True, True },
    { "IT", "Interviews", True, True },
	{ "AT", "Articles", True, True },
	{ "CV", "Magazine Covers", True, True },
	{ "SA", "Salary History", True, True },
	{ "PI", "Portrayed In", True, True },
	{ "PT", "Pictorial", True, True },
	{ NULL, NULL, False, False}
	};

void print_height(char *text) {
	int feet, inches, cm;
	float inches_f;
	char *cp;
	char unit[20];
	int value;
	char buf[256];

	if (strchr(text, '(') != 0) {
		/* assume that the conversion exists already in the data */
		AddToFilmbuf2("  ", text);
		return;
		}

	/* look for feet/inches data with a non-integer inch */
	if (sscanf(text, "%d' %f", &feet, &inches_f)==2) {
		inches=inches_f;
		if (inches!=inches_f) {
			cm = (feet*12 + inches_f) * 2.54 + 0.5;
			cp=strchr(text, '"')+1;
			sprintf(buf, "  %d' %.1f\" (%dcm) %s\n",
						feet, inches_f, cm, cp);
			AddToFilmbuf(buf);
			return;
			}
		}

	/* look for feet/inches data */
	if (sscanf(text, "%d' %d%s", &feet, &inches, unit)==3) {
		if (strcmp(unit, "\"")==0) {
			cm = (feet*12 + inches) * 2.54 + 0.5;
			cp=strchr(text, '"')+1;
			sprintf(buf, "  %d' %d\" (%dcm) %s\n",
					feet, inches, cm, cp);
			AddToFilmbuf(buf);
			return;
			}
		else if (strcmp(unit, "1/2\"")==0) {
			inches_f = inches+0.5;
			cm = (feet*12 + inches_f) * 2.54 + 0.5;
			cp=strchr(text, '"')+1;
			sprintf(buf, "  %d' %.1f\" (%dcm) %s\n",
					feet, inches_f, cm, cp);
			AddToFilmbuf(buf);
			return;
			}
		else if (strcmp(unit, "1/4\"")==0) {
			inches_f = inches+0.25;
			cm = (feet*12 + inches_f) * 2.54 + 0.25;
			cp=strchr(text, '"')+1;
			sprintf(buf, "  %d' %.2f\" (%dcm) %s\n",
				feet, inches_f, cm, cp);
			AddToFilmbuf(buf);
			return;
			}
		else if (strcmp(unit, "3/4\"")==0) {
			inches_f = inches+0.75;
			cm = (feet*12 + inches_f) * 2.54 + 0.75;
			cp=strchr(text, '"')+1;
			sprintf(buf, "  %d' %.2f\" (%dcm) %s\n",
				feet, inches_f, cm, cp);
			AddToFilmbuf(buf);
			return;
			}
		}

	unit[0]='\0';
	if (sscanf(text, "%d%s", &value, unit)==2) {
		if (strcmp(unit, "cm")==0) {
			cm=value;
			feet = ((float) cm)/30.48;
			inches = (cm - feet*30.48)/2.54;
			cp=strchr(text, 'm')+1;
			sprintf(buf, "  %d' %d\" (%dcm) %s\n",
					feet, inches, cm, cp);
			AddToFilmbuf(buf);
			return;
			}
		else if (strcmp(unit, "'")==0) {
			feet=value;
			cm = (feet*12) * 2.54 + 0.5;
			inches=0;
			cp=strchr(text, '\'')+1;
			sprintf(buf, "  %d' %d\" (%dcm) %s\n",
					feet, inches, cm, cp);
			AddToFilmbuf(buf);
			return;
			}
		}
	/* all else failed - just print it verbatim */
	AddToFilmbuf2("  ", text);
	}

void printHeight(struct lineRec *lrec) {
	struct lineRec *line;

	if (lrec==NULL)
		return;

	AddToFilmbuf("Height:\n");
	if (lrec->next != NULL) {
		/* just print everthing verbatim */
		for (line = lrec; line!=NULL; line=line->next) 
			AddToFilmbuf2("  ", line->text);
		return;
		}

	print_height(lrec->text);
	}

void printWrappedBulleted(struct lineRec *line) {
	static Buffer *buf=NULL;
	char *cp;

	if (buf==NULL)
		buf=CreateBuffer("bullet", 512, 512, 65536);

	ClearBuffer(buf);
	AddToFilmbuf("<w1>");
	while (line!=NULL) {
		if ((line->text[0] == '*') && !EmptyBuffer(buf)) {
			cp=insert_qv_links(buf->buf);
			trim_text2(cp, cp);
			AddToFilmbuf2(cp, "\n");
			ClearBuffer(buf);
			}
		if (line->text[0] == '*') {
			AddToBuffer(buf, "<b>");
			AddToBuffer(buf, line->text+2);
			}
		else
			AddToBuffer(buf, line->text);
		line = line->next;
		}

	if (!EmptyBuffer(buf)) {
		cp=insert_qv_links(buf->buf);
		trim_text2(cp, cp);
		AddToFilmbuf2(cp, "<i0>\n");
		}
	AddToFilmbuf("<w0>\n");
	}

void printBulleted(struct lineRec *line) {
	char *cp;

	while (line != NULL) {
		cp=insert_qv_links(line->text);
		if (*cp == '*') 
			AddToFilmbuf2("<b>", cp+2);
		else {
			while (*cp ==' ')
				cp++;
			AddToFilmbuf(cp);
			}
		line = line->next;
		}

	AddToFilmbuf("\n");
	}

void printBioMiscRec(struct bioMiscRec *rec) {
	struct lineRec *line;
	int i;
	char *cp;
	char buf[256];

	if (rec->list == NULL) 
		return;

	if (strncmp(rec->label, "HT", 2)==0) {
		printHeight(rec->list);
		return;
		}

	i=0;
	while (bio_info[i].key != NULL) {
		if (strncmp(rec->label, bio_info[i].key, 2)==0) {
			AddToFilmbuf3("<f5>", bio_info[i].heading, "<f1>\n");
			break;
			}
		i++;
		}

	if (bio_info[i].key == NULL) {
		sprintf(buf, "%c%c:\n\n", rec->label[0], rec->label[1]);
		AddToFilmbuf(buf);
		}

	if ((bio_info[i].bulleted) && (bio_info[i].wrapped)) {
		printWrappedBulleted(rec->list);
		return;
		}

	if (bio_info[i].bulleted) {
		printBulleted(rec->list);
		return;
		}

	for (line = rec->list; line!=NULL; line=line->next) {
		cp=insert_qv_links(line->text);
		if (bio_info[i].wrapped)
			AddToFilmbuf("<w1>");
		AddToFilmbuf2("  ", cp);
		if (bio_info[i].wrapped)
			AddToFilmbuf("<w0>");
		}

	AddToFilmbuf("\n");
	}

void printBioRec(struct bioRec *rec) {
	char *cp;

	if (rec->biog == NULL) 
		return;

	AddToFilmbuf("<f5>Biography<f1>\n");

	cp=insert_qv_links(rec->biog);
	AddToFilmbuf3("<w1>", cp, "<w0>\n");

	if (rec->BY != NULL)
		if (strstr(rec->BY, "Anonymous")==0)
			AddToFilmbuf3("Biography by:  ", rec->BY, "\n");
	}

void printBiography(struct personRec *rec, char *name, int biopt, struct akaNameRec *aka ) {
	struct bioRec *brec;
	struct bioMiscRec *miscptr ;
	struct akaNameRec *arec ;

	AddToFilmbuf("<f4><c4>Biographical data<f1><c1>\n");
	if (name!=NULL)
		AddToFilmbuf3("Name:  ", name, "\n\n");

	if (aka!=NULL) {
		AddToFilmbuf("Aka Names:\n");
		for (arec=aka; arec!=NULL; arec=arec->next)
			AddToFilmbuf3("  ", arec->akaName, "\n");
		AddToFilmbuf("\n");
		}

	if (rec!=NULL) {
		if (rec->RN != NULL)
			AddToFilmbuf3("<w1>Real Name: ", rec->RN, "<w0>\n");

		if (rec->DB != NULL)
			AddToFilmbuf3("<w1>Birth Date: ", rec->DB, "<w0>\n");

		if (rec->DD != NULL)
			AddToFilmbuf3("<w1>Death Date: ", rec->DD, "<w0>\n");

		for (brec=rec->biography; brec!=NULL; brec=brec->next)
			printBioRec(brec);

		for (miscptr=rec->misc; miscptr!=NULL; miscptr=miscptr->next)
			printBioMiscRec(miscptr);
		}
	}

void printName(struct nameSearchRec *nrec) {
	int i, j;
	struct listRec *films;
	struct listEntry theFilm;
	struct akaRec *aka;
	char buf[1024];

	/* display the biography */
	printBiography(nrec->biography, nrec->name, 
		nrec->searchparams.biopt, nrec->aka);

	AddToFilmbuf("<w1>");
	for (i=0; i<NO_OF_FILMOGRAPHY_LISTS; i++) {
		if (nchain->lists[i] == NULL) continue;

		AddToFilmbuf3("\n<f4><c4>Filmography as ", filmographyDefs[i].filmography, "\n<f1><c1>");
		films=nchain->lists[i];
		for (j=0; j<films->count; j++) {
			theFilm=films->entries[j];
			sprintf(buf, "%d.<i 25><l MOV:%s>%s<e>",j+1, theFilm.title, theFilm.title);
			AddToFilmbuf(buf);

			/* display film attributes */
			if (theFilm.attr != NULL)
				AddToFilmbuf3(" <f2>", theFilm.attr, "<f1>");

			/* display character names */
			if (theFilm.cname != NULL)
				if (app_data.chartab>0) {
					sprintf(buf, " <d %d> %s", app_data.chartab, theFilm.cname);
					AddToFilmbuf(buf);
					}
				else 
					AddToFilmbuf3(" [", theFilm.cname, "]");

			AddToFilmbuf("<i0>\n");

			/* display a.k.a.'s */
			for (aka=theFilm.aka; aka!=NULL; aka=aka->next) {
				AddToFilmbuf2("<i 50>... aka <f2>", aka->akaTitle);
				if (aka->akaAttr != NULL)
					AddToFilmbuf2("  ", aka->akaAttr);
				AddToFilmbuf("<f1><i0>\n");
				}
			}
		}
	AddToFilmbuf("<w0>");
	AddToFilmbuf3("\n<m1><f2>", COPYRIGHT, "<f1><m0>");
	}
