#import <appkit/graphics.h>
#import <appkit/Window.h>
#import <appkit/PopUpList.h>
#import <appkit/Matrix.h>
#import <appkit/Cell.h>
#import <objc/List.h>
#import <signal.h>
#import "StateManager.h"
#import "Filter.h"
#import "Script.h"
#import "FilterInspector.h"
#import "ScriptInspector.h"
#import "HelpManager.h"
#import "support.h"

@implementation Filter

#define FILTER_VERSION 1
#define NOTSET strdup("")

+ initialize
{
	[Filter setVersion: FILTER_VERSION];
	return self;
}

- init
{
	[super init];
	filterName = NOTSET;
	command = NOTSET;
	destination = NOTSET;
	menu = NOTSET;
	items = NOTSET;
	selectedItem = NOTSET;
	return self;
}

- setStateManager: anObject
{
	stateManager = anObject;
	inspector = [stateManager filterInspector];
	return self;
}

- parameterChanged
{
	filterName = stringDup(filterName, [inspector filterName]);
	command = stringDup(command, [inspector command]);
	destination = stringDup(destination, [inspector destination]);
	inputFromStdin = [inspector inputFromStdin];
	outputToStdout = [inspector outputToStdout];
	menu = stringDup(menu, [inspector menu]);
	return self;
}

- nameChanged
{
	filterName = stringDup(filterName, [nameCell stringValue]);
	return self;
}

- (char *) filterName	{return filterName;}
- (char *) command	{return command;}
- (char *) destination	{return destination;}
- (int) inputFromStdin	{return inputFromStdin;}
- (int) outputToStdout	{return outputToStdout;}
- (char *) menu		{return menu;}

- update
{
	char *p, *q;

	[popupList free];
	[menuList free];
	free(items);
	popupList = [[PopUpList alloc] init];
	menuList = [[List alloc] init];
	p = items = strdup(menu);
	while (q = parse_quote(p, &p)) {
		[popupList addItem: q];
		q = parse_quote(p, &p);
		[menuList addObject: q];
	}
	[popupList removeItem: ""];
	[nameCell setStringValue: filterName];
	[optionCell setTarget: popupList];
	[optionCell setAction: @selector(popUp:)];
	[optionCell setTitle: [self selectedItem]];
	[popupList setTarget: self];
	[popupList setAction: @selector(popupSelected:)];
	return self;
}

- popupSelected: sender
{
	selectedItem = stringDup(selectedItem, [popupList selectedItem]);
}

- (const char *) selectedItem
{
	if (!popupList || [popupList indexOfItem: selectedItem] == -1) {
		return "";
	} else {
		return selectedItem;
	}
}

- setNameCell: anObject
{
	nameCell = anObject;
	return self;
}

- setOptionCell: anObject
{
	optionCell = anObject;
	return self;
}

- (char *) assignVariable: (char *)iconPathList to: (char *) line
{
	char *path, *leader, *p, *q;
	char *basename, *rootname, *srcDir;

	if (iconPathList == NULL) {
		basename = rootname = srcDir = "";
	} else {
		//	chop path-prefixes, basenames from iconPathList
		path = strdup(iconPathList);
		p = rindex(path, '/');
		basename = strdup(p+1);
		q = rindex(path, '.');
		if (q) *q = '\0';
		rootname = strdup(p+1);
		*p = '\0';
		srcDir = strdup(path);
	}
	*assigned = '\0';
	leader = p = strdup(line);
	while (1) {
		q = index(p, '$');
		if (q == NULL)  break;
		*q = '\0';
		strcat(assigned, p);
		p = q+2;
		switch (q[1]) {
		case 'i':
			strcat(assigned, basename);
			break;
		case 'r':
			strcat(assigned, rootname);
			break;
		case 's':
			strcat(assigned, srcDir);
			break;
		case 'm':
			if (popupList) {
				strcat(assigned,
					[menuList objectAt: [popupList indexOfItem: [self selectedItem]]]);
			}
			break;
		default:
			q[0] = q[2];
			q[1] = '\0'	;	// messy..
			strcat(assigned, q);
			break;
		}
	}
	strcat(assigned, p);

	if (iconPathList) {
		free(path);
		free(leader);
		free(basename);
		free(rootname);
		free(srcDir);
	}
	return assigned;
}

- setPathname: (char *) aString
{
	pathname = stringDup(pathname, aString);
	return self;
}
- (char *) pathname
{
	return pathname;
}

- write: (NXTypedStream *)ts
{
	[super write: ts];
	NXWriteTypes(ts, "*****ii", &filterName, &command, &destination,
					&menu, &selectedItem, &inputFromStdin, &outputToStdout);
	return self;
}

- read: (NXTypedStream *)ts
{
	[super read: ts];
	if (NXTypedStreamClassVersion(ts, [self name]) != FILTER_VERSION) {
		NXRunAlertPanel(NULL, "Specified file contains contains incompatible data.\n"
							"You might have specified non-filter file.",
					"OK", NULL, NULL);
		return nil;
	}
	NXReadTypes(ts, "*****ii", &filterName, &command, &destination,
					&menu, &selectedItem, &inputFromStdin, &outputToStdout);
	return self;
}

@end
