#import "ETAppDelegate.h"

static int inExit = 0;
static void ExitTcl(int status);
static int ExitObjCmd(ClientData dummy,	Tcl_Interp *interp, int objc,
	Tcl_Obj *const objv[]);
static int EuroTclDemoObjCmd(ClientData dummy,	Tcl_Interp *interp, int objc,
	Tcl_Obj *const objv[]);

@implementation ETAppDelegate

@synthesize textField, webView, interp, demoWindow;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    id b = [NSBundle mainBundle];

    self.interp = [self initTcl:[b bundlePath]
	    lib:[b pathForResource:@"lib" ofType:nil]
	    args:[NSArray arrayWithObjects:
		    [[b pathForResource:@"wubwikit" ofType:nil]
		    stringByAppendingString:@"/main.tcl"],
		    @"wub", @"1", @"wikidb",
		    [b pathForResource:@"wikit" ofType:@"tkd"], nil]];

    [self.webView makeTextLarger:nil]; [self.webView makeTextLarger:nil];
    [[self.webView mainFrame] loadRequest:[NSURLRequest requestWithURL:
	    [NSURL URLWithString:@"http://localhost:8080/22566"]]];
}

- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)sender {
    return YES;
}

- (void)applicationWillTerminate:(NSNotification *)notification {
    if (self.interp) {
	[self finalizeTcl:self.interp];
	self.interp = NULL;
    }
}

- (void)finalize {
    [self applicationWillTerminate:nil];
    [super finalize];
}

- (void)webView:(WebView *)sender
	didStartProvisionalLoadForFrame:(WebFrame *)frame
{
    if (frame == [sender mainFrame]){
        [textField setStringValue:[[[[frame provisionalDataSource] request]
		URL] absoluteString]];
    }
}

- (Tcl_Interp*)initTcl:(NSString*)app lib:(NSString*)lib args:(NSArray*)args {
    Tcl_FindExecutable([app UTF8String]);
    Tcl_SetExitProc((Tcl_ExitProc*) ExitTcl);
    Tcl_SetServiceMode(TCL_SERVICE_ALL);
    Tcl_Interp *i = Tcl_CreateInterp();
    Tcl_InitMemory(i);

    if ([args count]) {
	app = [args objectAtIndex:0];
	Tcl_SetStartupScript(Tcl_NewStringObj([app UTF8String], -1), NULL);
	args = [args mutableCopy];
	[(NSMutableArray*)args removeObjectAtIndex:0];
    }
    Tcl_Obj *argv = Tcl_NewListObj(0, NULL);
    for (NSString *s in args) {
	Tcl_ListObjAppendElement(NULL, argv,
		Tcl_NewStringObj([s UTF8String], -1));
    }
#define ET_SetTclVar(n,o) Tcl_SetVar2Ex(i, n, NULL, o, TCL_GLOBAL_ONLY)
    ET_SetTclVar("argv0",	    Tcl_NewStringObj([app UTF8String], -1));
    ET_SetTclVar("tcl_library",	    Tcl_NewStringObj([lib UTF8String], -1));
    ET_SetTclVar("argc",	    Tcl_NewIntObj([args count]));
    ET_SetTclVar("argv",	    argv);
    ET_SetTclVar("tcl_interactive", Tcl_NewBooleanObj(0));
#undef ET_SetTclVar

    Tcl_Preserve(i);
    int result = Tcl_Init(i);
    if (result == TCL_OK) {
	Tcl_CreateObjCommand(i, "exit", ExitObjCmd, NULL, NULL);
	Tcl_CreateObjCommand(i, "EuroTclDemo", EuroTclDemoObjCmd, NULL, NULL);
	Tcl_Obj *path = Tcl_GetStartupScript(NULL);
	if (path) {
	    result = Tcl_FSEvalFileEx(i, path, NULL);
	}
    }
    if (result == TCL_ERROR) {
	NSLog(@"Tcl initialization failed: %s\n",
		Tcl_GetString(Tcl_GetObjResult(i)));
    }
    if (result == TCL_ERROR || Tcl_InterpDeleted(i) ||
	    Tcl_LimitExceeded(i)) {
	[self finalizeTcl:self.interp];
	i = NULL;
    }
    return i;
}

- (void)finalizeTcl:(Tcl_Interp*)i {
    if (!inExit) {
	if (!Tcl_InterpDeleted(i)) {
	    Tcl_DeleteInterp(i);
	}
	Tcl_Release(i);
    }
    Tcl_Finalize();
}

- (NSString *)euroTclDemo {
    [self.demoWindow makeKeyAndOrderFront:self];
    return @"returning a result";
}

@end

static void ExitTcl(int status) {
    inExit = 1;
    [NSApp terminate:nil];
    exit(status);
}

static int ExitObjCmd(ClientData dummy,	Tcl_Interp *interp, int objc,
	Tcl_Obj *const objv[]) {
    int value;

    if ((objc != 1) && (objc != 2)) {
	Tcl_WrongNumArgs(interp, 1, objv, "?returnCode?");
	return TCL_ERROR;
    }

    if (objc == 1) {
	value = 0;
    } else if (Tcl_GetIntFromObj(interp, objv[1], &value) != TCL_OK) {
	return TCL_ERROR;
    }
    [NSApp stop:nil];
    return TCL_OK;
}

static int EuroTclDemoObjCmd(ClientData dummy,	Tcl_Interp *interp, int objc,
	Tcl_Obj *const objv[]) {
    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, "");
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewStringObj([[[NSApp delegate] euroTclDemo]
	    UTF8String], -1));
    return TCL_OK;
}

