#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/List.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/Command.h>
#include "LinkView.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "moviedb.h"
#include "xregal.h"
#include "popup.h"

/* include files from imoviedb package */
#undef DBDIR
#include "config.h"
#include "imoviedb.h"
#include "array.h"
#include "readname.h"


static void complete(Widget w,
                     XEvent *event,
                     String *params,
                     Cardinal *num_params);
static void searchFromList(Widget w,
                     XEvent *event,
                     String *params,
                     Cardinal *num_params);
                     
static Array *titleArray=NULL, *nameArray=NULL;
static Widget compl_list=NULL, c_shell;
static XtActionsRec actionTable[] = {{"complete",complete},
                                     {"searchFromList",searchFromList}};
static void PopupComplResults(unsigned char **, String, int);
void CreateCompletionDialog(Widget);

static String myDouble = "<Btn1Up>(2):   searchFromList()\n";
static XtTranslations doubleTransl=NULL;

extern Widget ns_search, ts_search, nse_text, tse_text, ts_shell, ns_shell;
Widget curSearch, curTxt, curShell;

static void complete(Widget w,
                     XEvent *event,
                     String *params,
                     Cardinal *num_params) {
	char *stringBegin, *newBegin;
	ArrayCompletion *ac;
	int iElems=0;
	unsigned char **compList=NULL, **completions, **pc;
  
	XtVaGetValues(w,XtNstring,&stringBegin,	NULL);
	if (!strcmp(params[0], "Name")) {

		/* if the name data isn't yet loaded - do it now */
		if (!nameArray) {
			nameArray =  readname_loadname(NAMECOMPL, NAMEKEY);
			if (nameArray == NULL) {
				Alert("Error loading name completion data.");
				return;
				}
			}

		ac=array_createcompletion(nameArray);
		curSearch=ns_search;
		curTxt=nse_text;
		curShell=ns_shell;
	} else if (!strcmp(params[0], "Title")) {

		/* if the title data isn't yet loaded - do it now */
		if (!titleArray) {
			titleArray =  readname_loadtitle(TITLECOMPL, TITLEKEY, TRUE, 0, 0);
			if (titleArray == NULL) {
				Alert("Error loading title completion data.");
				return;
				}
			}

		ac=array_createcompletion(titleArray);
		curSearch=ts_search;
		curTxt=tse_text;
		curShell=ts_shell;
	} else {
		fprintf (stderr, "Error: unrecognized action\n");
		return;
		}

	array_trycompletion(ac, stringBegin);  
	if (array_nbofcompletionshigherthan (ac, 200)) {
		Alert ("More than 200 matches!");
		array_destroycompletion (ac);
		return;
	} else 
		completions=array_getallcompletions(ac, &iElems);
  
	/* Looking for TV  */
	if (!strcmp(params[0], "Title") && (stringBegin[0] != '"')) {
		int iTvElems=0;
		unsigned char **newCompl;
  
		newBegin=XtCalloc(strlen(stringBegin)+2, sizeof(char));
		newBegin[0]='"';
		strcat(newBegin, stringBegin);
		array_trycompletion(ac, newBegin);
		newCompl= array_getallcompletions(ac, &iTvElems);
		if (!iElems) {
			if (!iTvElems) {
				array_destroycompletion (ac);
				Alert("No matches found!");
				return;
				}
			completions = newCompl;
			} 
		else if (iTvElems) {
			completions = (unsigned char **)XtRealloc((XtPointer)completions, 
				(iElems+iTvElems+1)*sizeof(String));
			memcpy(completions+iElems, newCompl, (iTvElems+1)*sizeof(String));
			free (newCompl);
			}
		iElems += iTvElems;
		}

	if (!iElems)
		Alert("No matches found!");
	else if (iElems > 200) {
		Alert ("More than 200 matches!");
		for (pc=completions; *pc; free(*(pc++)));
		free (completions);
		}
	else if (iElems==1) {
		XtVaSetValues(curTxt, XtNstring, completions[0], NULL);
		free(completions[0]);
		free(completions);
		}
	else {
		int iHowMany=0;
  
		XtVaGetValues(compl_list, XtNlist, &compList, XtNnumberStrings, &iHowMany, NULL);
		PopupComplResults(completions, params[0], iElems);
		if (compList) {
			for (; iHowMany>0; free(compList[--iHowMany]));
			free (compList);
			}
		}
	array_destroycompletion (ac);
	}



static void searchFromList(Widget w,
                     XEvent *event,
                     String *params,
                     Cardinal *num_params) {

  if (XawListShowCurrent(w)->list_index ==  XAW_LIST_NONE)
    return;

  XtPopdown(c_shell);
	XtVaSetValues(curTxt, XtNstring, XawListShowCurrent(w)->string, NULL);
	XtCallCallbacks(curSearch, XtNcallback, 0);
}



static void Cancel(Widget w, XtPointer client_data, XtPointer call_data) {
	XtPopdown(c_shell);
	}



static void Apply(Widget w, XtPointer client_data, XtPointer call_data) {
	searchFromList(compl_list,NULL,NULL,NULL);
	}



void addNameCompletion(void) {
	static String myTab = "<Key>Tab:   complete(Name)\n";
	static XtTranslations tabTransl=NULL;
   
	if (!nameArray  && (strcmp(app_data.nameCompletion, "on") == 0)) {
		nameArray =  readname_loadname(NAMECOMPL, NAMEKEY);
		if (nameArray == NULL) {
			Alert("Error loading name completion data.");
			return;
			}
		}
	if (!compl_list)
		CreateCompletionDialog(ns_shell);
	if (!tabTransl) 
		tabTransl = XtParseTranslationTable(myTab);
	XtOverrideTranslations(nse_text, tabTransl);
	}



void addTitleCompletion(void) {
	static String myTab = "<Key>Tab:   complete(Title)\n";
	static XtTranslations tabTransl=NULL;

	if (!titleArray && (strcmp(app_data.nameCompletion, "on") == 0)) {
		titleArray =  readname_loadtitle(TITLECOMPL, TITLEKEY, TRUE, 0, 0);
		if (titleArray == NULL) {
			Alert("Error loading title completion data.");
			return;
			}
		}

	if (!compl_list)
		CreateCompletionDialog(ts_shell);
	if (!tabTransl) 
		tabTransl = XtParseTranslationTable(myTab);
	XtOverrideTranslations(tse_text, tabTransl);
	}



void CreateCompletionDialog(Widget parent) {
  Widget c_form,c_apply,c_cancel,compl_view;
  char **pcDummy;
  static String myreturn = "#override <Key>Return:   set() notify() unset()\n";
  static String myescape = "#override <Key>Escape:   set() notify() unset()\n";
  XtAccelerators escaccel;
  XtAccelerators accel;
  Dimension spacing;
  XFontStruct *font;

  accel = XtParseAcceleratorTable(myreturn);
  escaccel = XtParseAcceleratorTable(myescape);

  c_shell=XtVaCreatePopupShell(
                "c_shell",
                transientShellWidgetClass,
                parent,
                XtNallowShellResize, True,
                NULL);

  c_form=XtVaCreateManagedWidget("c_form",formWidgetClass,c_shell, NULL);

  compl_view=XtVaCreateManagedWidget("compl_view",linkViewWidgetClass,c_form,
        XtNwidth, 300,
        XtNheight, 170,
        XtNborderWidth, 2,
        XtNallowVert, True,
        XtNallowHoriz, False,
		XtNbottom, XtChainBottom,
        NULL);

  /* create an empty list (will be freed) when actual list pops up) */
  pcDummy=calloc(2,sizeof(char *));
  pcDummy[0]=strdup("");

  compl_list=XtVaCreateManagedWidget("compl_list",listWidgetClass,compl_view,
        XtNwidth, 100,
        XtNdefaultColumns, 1,
        XtNforceColumns, True,
        XtNlist, pcDummy,
        NULL);

  XtVaGetValues(compl_list, XtNrowSpacing, &spacing, XtNfont, &font, NULL);
  spacing +=  font->max_bounds.ascent + font->max_bounds.descent;
  XtVaSetValues(compl_view, XtNbaselineskip, spacing, NULL);

  c_apply=XtVaCreateManagedWidget("c_search",commandWidgetClass,c_form,
        XtNfromVert, compl_view,
		XtNlabel, "Search",
        XtNaccelerators, accel,
		XtNleft, XtChainLeft,
		XtNright, XtChainLeft,
		XtNtop, XtChainBottom,
		XtNbottom, XtChainBottom,
		NULL);
  c_cancel=XtVaCreateManagedWidget("c_cancel",commandWidgetClass,c_form,
        XtNfromVert, compl_view,
		XtNfromHoriz, c_apply,
		XtNlabel, "Cancel",
        XtNaccelerators, escaccel,
		XtNleft, XtChainLeft,
		XtNright, XtChainLeft,
		XtNtop, XtChainBottom,
		XtNbottom, XtChainBottom,
		NULL);

  XtAddCallback(c_cancel, XtNcallback, Cancel, 0);
  XtAddCallback(c_apply, XtNcallback, Apply, 0);
  XtSetKeyboardFocus(c_form, compl_view);
  XtInstallAccelerators(compl_view, c_cancel);
  XtInstallAccelerators(compl_view, c_apply);

  if (!doubleTransl) {
    XtAppAddActions(app_context, actionTable, 2);
    doubleTransl = XtParseTranslationTable(myDouble);
  }
  XtOverrideTranslations(compl_list, doubleTransl);
}


	
static void PopupComplResults(unsigned char **list, String what, int iHowMany) {
	String title;
	
	title=XtCalloc(13+strlen(what),sizeof(char));
	strcpy(title, what);
	strcat(title, " completions");
	XawListChange(compl_list, (String *) list, iHowMany, 0, True);
	XtVaSetValues(c_shell, XtNtitle, title, NULL);
	XtFree(title); 
	SetPopupPosition(c_shell, curShell);
	XtPopup(c_shell, XtGrabExclusive);
	}


