/* Copyright (c) 1993 by Sanjay Ghemawat */
#include <stdio.h>
#include <string.h>

extern "C" {
#include <tcl.h>
#include <tk.h>
}

#include "commands.h"

static char initTk[] = "source $tk_library/wish.tcl";
static char initTcl[] = "source [info library]/init.tcl";


static Tk_Window window;
static void map_window(ClientData);
static void destroy_proc(ClientData, XEvent*);

/*
 * Options specified on command line.
 */

static char* display = 0;
static char* geometry = 0;
static char* file = 0;
static char* name = "calshell";

static Tk_ArgvInfo arguments[] = {
    { "-name",     TK_ARGV_STRING, 0, (char*)&name,     "Application name" },
    { "-display",  TK_ARGV_STRING, 0, (char*)&display,  "X Display" },
    { "-geometry", TK_ARGV_STRING, 0, (char*)&geometry, "Initial geometry" },
    { "-f",        TK_ARGV_STRING, 0, (char*)&file,     "Tcl script" },
    { 0,	   TK_ARGV_END,    0, 0,                0 }
};

int
main(int argc, char* argv[]) {
    Tcl_Interp* tcl = Tcl_CreateInterp();

    if (Tk_ParseArgv(tcl, (Tk_Window) 0, &argc, argv, arguments, 0) != TCL_OK){
	fprintf(stderr, "%s\n", tcl->result);
	return 1;
    }

    if ((file == 0) && (argc > 1)) {
	file = argv[1];
	argc--;
	argv++;
    }

    if (file == 0) {
	fprintf(stderr, "no tcl script specified\n");
	return 1;
    }

    /* Set name */
    if (name == 0) {
	name = strrchr(file, '/');
	if (name != 0) {
	    name++;
	}
	else {
	    name = file;
	}
    }

    window = Tk_CreateMainWindow(tcl, display, name);
    Tcl_SetVar(tcl, "nowindow", (window == NULL) ? "1" : "0", TCL_GLOBAL_ONLY);

    /* Make argc/argv available to TCL code */
    char buffer[20];
    sprintf(buffer, "%d", argc-1);
    char* args = Tcl_Merge(argc-1, argv+1);

    Tcl_SetVar(tcl, "argc", buffer, TCL_GLOBAL_ONLY);
    Tcl_SetVar(tcl, "argv", args, TCL_GLOBAL_ONLY);

    Tcl_CreateCommand(tcl, "calendar",     Cmd_CreateCalendar,	NULL, NULL);
    Tcl_CreateCommand(tcl, "notice",       Cmd_CreateNotice,	NULL, NULL);
    Tcl_CreateCommand(tcl, "appointment",  Cmd_CreateAppt,	NULL, NULL);
    Tcl_CreateCommand(tcl, "cclass",       Cmd_CharClass,	NULL, NULL);
    Tcl_CreateCommand(tcl, "date",         Cmd_Date,		NULL, NULL);
    Tcl_CreateCommand(tcl, "time",         Cmd_Time,		NULL, NULL);
    Tcl_CreateCommand(tcl, "psmonth",      Cmd_PsMonth,		NULL, NULL);
    Tcl_CreateCommand(tcl, "psdays",       Cmd_PsDays,		NULL, NULL);
    Tcl_CreateCommand(tcl, "de_monthdays", Cmd_MonthDays,	NULL, NULL);
    Tcl_CreateCommand(tcl, "de_interest",  Cmd_InterestTags,	NULL, NULL);

    if (window != NULL) {
	Tk_SetClass(window, "Ical");
	Tk_GeometryRequest(window, 200, 200);
	Tk_CreateEventHandler(window, StructureNotifyMask, destroy_proc, 0);
	Tk_DoWhenIdle(map_window, 0);

	if (geometry != 0) {
	    Tcl_SetVar(tcl, "geometry", geometry, TCL_GLOBAL_ONLY);
	}

	Tcl_CreateCommand(tcl, "wraise", Cmd_WindowRaise,
			  (ClientData)window, NULL);
	Tcl_CreateCommand(tcl, "wbeep", Cmd_Beep, (ClientData)window, NULL);
    }

    if (window == NULL) {
	if (Tcl_Eval(tcl, initTcl, 0, NULL) != TCL_OK) {
	    fprintf(stderr, "init error: %s\n", tcl->result);
	    return 1;
	}
    }
    else {
	if (Tcl_Eval(tcl, initTk, 0, NULL) != TCL_OK) {
	    fprintf(stderr, "init error: %s\n", tcl->result);
	    return 1;
	}
    }

    if (Tcl_EvalFile(tcl, file) == TCL_ERROR) {
	fprintf(stderr, "%s\n", tcl->result);
	return 1;
    }

    if (window != NULL) {
	Tk_MainLoop();
    }

    Tcl_DeleteInterp(tcl);
    return 0;
}

/*
 * modifies	window
 * effects	If event is a destroy notification, modify window to NULL.
 */
static void destroy_proc(ClientData, XEvent* event) {
    if (event->type == DestroyNotify) {
	window = NULL;
    }
}

/*
 * requires	Called by Tk event dispatcher
 * effects	Main window gets mapped after all idle handlers have
 *		been processed.
 */
static void map_window(ClientData c) {
    while (Tk_DoOneEvent(TK_IDLE_EVENTS) != 0) {
    }

    if (window != NULL) {
	Tk_MapWindow(window);
    }
}
