#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/Xaw/List.h>
#include <X11/Xaw/Command.h>
#include "history.h"
#include "LinkView.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "LinkText.h"
#include "popup.h"
#include "xregal.h"


HTscreen *history_head=NULL;
HTscreen *history_current=NULL;

/* count how many screens are in the history list */

int historySize(void) {
	int i=0;
	HTscreen *p=history_head;

	while (p!=NULL) {
		p = p->next;
		i++;
		}
	return i;
	}

Boolean isLastHistory(void) {
	if (history_current==NULL)
		return True;
	return (history_current->next == NULL);
	}

Boolean isFirstHistory(void) {
	if (history_current==NULL)
		return True;
	return (history_current->prev == NULL);
	}

void sensifyButtons(void) {
	XtVaSetValues(backbutton, XtNsensitive, !isFirstHistory(), NULL);
	XtVaSetValues(forwardbutton, XtNsensitive, !isLastHistory(), NULL);
	XtVaSetValues(historybutton, XtNsensitive, historySize()>1, NULL);
	}

HTscreen *createHTscreen(char *htext, char *title, char *url) {
	HTscreen *newscreen;

	newscreen=(HTscreen*) XtMalloc (sizeof(HTscreen));
	newscreen->hypertext= XtNewString(htext);
	newscreen->title = XtNewString(title);
	if (url==NULL)
		newscreen->url = NULL;
	else 
		newscreen->url = XtNewString(url);
	newscreen->next=NULL;
	newscreen->prev=NULL;
	return newscreen;
	}

void freeHTscreen(HTscreen *scr) {
	XtFree(scr->hypertext);
	XtFree(scr->title);
	if (scr->url != NULL)
		XtFree(scr->url);
	XtFree((char*)scr);
	}

void freeHistory(HTscreen *scr) {
	if (scr==NULL)
		return;
	freeHistory(scr->next);
	freeHTscreen(scr);
	}

void historySavePosition(void) {
	int x, y;

	if (app_data.historyMax<=0)
		return;

	if (history_current!=NULL) {
		LinkViewGetCoordinates(vport, &x, &y);
		history_current->viewport_x = x;
		history_current->viewport_y = y;
		}
	}

void historyAdd(char *htext, char *title, char *url) {
	HTscreen *top;

	if (app_data.historyMax<=0)
		return;

	if (history_head==NULL) {
		history_head=createHTscreen(htext, title, url);
		history_current=history_head;
		}
	else {
		if (history_current->next != NULL)
			freeHistory(history_current->next);
		history_current->next =createHTscreen(htext, title, url);
		history_current->next->prev = history_current;
		history_current = history_current->next;
		}
	if (historySize()>app_data.historyMax) {
		top=history_head;
		history_head=history_head->next;
		history_head->prev = NULL;
		freeHTscreen(top);
		}
	sensifyButtons();
	}

HTscreen *previousHistory(void) {
	if (app_data.historyMax<=0)
		return NULL;

	if (history_current->prev == NULL)
		return NULL;
	history_current = history_current->prev;
	return history_current;
	}

HTscreen *nextHistory(void) {
	if (app_data.historyMax<=0)
		return NULL;

	if (history_current->next == NULL)
		return NULL;
	history_current = history_current->next;
	return history_current;
	}


static void DrawHistory(HTscreen *screen) {
	SetTitle(screen->title);
	XtVaSetValues(viewer, XtNhypertext, screen->hypertext, NULL);
	LinkViewReload(vport, screen->viewport_x, screen->viewport_y);
	XtVaSetValues(url_text, XtNstring, 
		(screen->url !=NULL) ? screen->url : "", NULL);
}

void GoBack(void) {
	if (app_data.historyMax<=0)
		return;

	if (isFirstHistory())
		return;
	historySavePosition();
	DrawHistory(previousHistory());
	sensifyButtons();
	}

void GoForward(void) {
	if (app_data.historyMax<=0)
		return;

	if (isLastHistory())
		return;
	historySavePosition();
	DrawHistory(nextHistory());
	sensifyButtons();
	}

void backCB(Widget w, XtPointer closure, XtPointer call_data) {
	GoBack();
	}

void forwardCB(Widget w, XtPointer closure, XtPointer call_data) {
	GoForward();
	}

/* History list management */

static String *historyTitles=NULL;
static Widget h_list=NULL, h_shell;

void PopupHistory(void) {
	HTscreen *p=history_head;
	int iHowMany=0;

	if (!XtIsSensitive(historybutton)) return;
	while (p!=NULL) {
		historyTitles[iHowMany] = p->title;
		p=p->next;
		iHowMany++;
	}
	XawListChange(h_list,historyTitles,iHowMany,0,True);
	SetPopupPosition(h_shell, topLevel);
	XtPopup(h_shell, XtGrabExclusive);
}

void historyCB(Widget w, XtPointer closure, XtPointer call_data) {
	PopupHistory();
}

static void historyFromList(Widget w,
                     XEvent *event,
                     String *params,
                     Cardinal *num_params) {
	int iIndex=XawListShowCurrent(w)->list_index;

  if (iIndex ==  XAW_LIST_NONE)
    return;

  XtPopdown(h_shell);
	historySavePosition();
	history_current=history_head;
  while(iIndex>0) {
  	nextHistory();
  	iIndex--;
  }
  DrawHistory(history_current);
	sensifyButtons();
}

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

static void Apply(Widget w, XtPointer client_data, XtPointer call_data) {
	historyFromList(h_list,NULL,NULL,NULL);
	}

void CreateHistoryDialog(void) {
  Widget h_form,h_apply,h_cancel,h_view;
  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;
  static XtActionsRec actionTable[] = {{"historyFromList",historyFromList}};
  static String myDouble = "<Btn1Up>(2):   historyFromList()\n";
  static XtTranslations doubleTransl=NULL;

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

  h_shell=XtVaCreatePopupShell(
                "h_shell",
                transientShellWidgetClass,
                topLevel,
                XtNallowShellResize, True,
                XtNtitle,"History",
                NULL);

  h_form=XtVaCreateManagedWidget("h_form",formWidgetClass,h_shell, NULL);

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

	historyTitles=(String *)XtCalloc(app_data.historyMax,sizeof(String));
	
  h_list=XtVaCreateManagedWidget("h_list",listWidgetClass,h_view,
        XtNwidth, 100,
        XtNdefaultColumns, 1,
        XtNforceColumns, True,
        XtNlist, historyTitles,
        NULL);

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

  h_apply=XtVaCreateManagedWidget("h_apply",commandWidgetClass,h_form,
        XtNfromVert, h_view,
		XtNlabel, "Go",
        XtNaccelerators, accel,
		XtNleft, XtChainLeft,
		XtNright, XtChainLeft,
		XtNtop, XtChainBottom,
		XtNbottom, XtChainBottom,
		NULL);
  h_cancel=XtVaCreateManagedWidget("h_cancel",commandWidgetClass,h_form,
        XtNfromVert, h_view,
		XtNfromHoriz, h_apply,
		XtNlabel, "Cancel",
        XtNaccelerators, escaccel,
		XtNleft, XtChainLeft,
		XtNright, XtChainLeft,
		XtNtop, XtChainBottom,
		XtNbottom, XtChainBottom,
		NULL);

  XtAddCallback(h_cancel, XtNcallback, Cancel, 0);
  XtAddCallback(h_apply, XtNcallback, Apply, 0);
  XtSetKeyboardFocus(h_form, h_view);
  XtInstallAccelerators(h_view, h_cancel);
  XtInstallAccelerators(h_view, h_apply);

  XtAppAddActions(app_context, actionTable, 2);
  doubleTransl = XtParseTranslationTable(myDouble);
  XtOverrideTranslations(h_list, doubleTransl);
}
