/*
	Copyright (C) 1994 Sean Luke

	COWSController.m
	Version 1.4
	Sean Luke
	
	Allows easy hookup to libraries and control nib and interpreter
	
*/

#import "COWSController.h"
#import "COWSInterpreter.h"
#import "COWSStringNode.h"
#import <string.h>
#import <stdlib.h>


@implementation COWSController

- init
	{
	timed_entry_speed=.1;			// default
	pulses_per_timed_entry=100;		// default
	autostart=COWSCONTROLLER_AUTOLOADANDRUN;
	inited=YES;
	return [super init];
	}

- awake
	{
	inited=YES;
	return [super awake];
	}

- _load
	{
	char* prog;
	
	if (program&&[program isKindOf:[Text class]])
		{
		int length=[program textLength];
		prog=malloc(length + 1);
		[program getSubstring:prog start:0 length:length];
		prog[length]='\0';					// some bug in Text object
		}
	else
		{
		printf ("COWS Controller Warning:  no program\n");
		prog=malloc(1);
		prog[0]='\0';
		}
	
	if (interpreter&&[interpreter conformsTo:@protocol(InterpreterControl)])
		{
		[interpreter clearLibraryFunctions];
		if (library1)	[interpreter addLibrary:library1];
		if (library2)	[interpreter addLibrary:library2];
		if (library3)	[interpreter addLibrary:library3];
		if (library4)	[interpreter addLibrary:library4];
		if (library5)	[interpreter addLibrary:library5];
		if (library6)	[interpreter addLibrary:library6];
		if (library7)	[interpreter addLibrary:library7];
		if (library8)	[interpreter addLibrary:library8];
		//if (delegate&&[delegate respondsTo:@selector(loadLibraries)])
		//	[delegate loadlibraries];
		if ([interpreter setProgram:prog]<0)
			{
			printf ("COWS Controller ERROR:  Syntax Error in Program Load\n");
			free(prog);
			return NULL;
			}
		}
	else 
		{
		printf ("COWS Controller ERROR:  no interpreter to load!\n");
		free(prog);
		return NULL;
		}
	free(prog);
	return self;
	}
	
- _run		
	{
	id args, new_args;

	if (interpreter&&[interpreter conformsTo:@protocol(InterpreterControl)])
		{
		if ([interpreter working])
			{
			printf 
			  ("COWS User Controller ERROR:  interpreter already working!\n");
			return NULL;
			}
		args=[[COWSArgumentList alloc] init];
		if (strlen(initial_arg1))
			{
			id temp=[[COWSStringNode alloc] init];
			[temp setString:initial_arg1];
			[args push:temp];
			if (strlen(initial_arg2))
				{
				id temp=[[COWSStringNode alloc] init];
				[temp setString:initial_arg2];
				[args push:temp];
				if (strlen(initial_arg3))
					{
					id temp=[[COWSStringNode alloc] init];
					[temp setString:initial_arg3];
					[args push:temp];
					if (strlen(initial_arg4))
						{
						id temp=[[COWSStringNode alloc] init];
						[temp setString:initial_arg4];
						[args push:temp];
						}	
					}	
				}	
			}	
	
		// this is in wrong order...so reverse it...
	
		new_args=[[COWSArgumentList alloc] init];
		while([args top]!=NULL)
			{
			[new_args push:[args pop]];
			}
		[args free];

		[interpreter interpretFunction:initial_function arguments:new_args];
		[new_args free];
		}
	else
		{
		printf ("COWS User Controller ERROR:  no interpreter to run!\n");
		return NULL;
		}
	return self;
	}
	
- awakeFromNib
	{
	if (interpreter&&[interpreter conformsTo:@protocol(InterpreterControl)])
		{
		[interpreter printErrors:YES];
		[interpreter setTimedEntrySpeed:timed_entry_speed];
		[interpreter setRepeats:pulses_per_timed_entry];
		[interpreter setLocked:locked];
		[interpreter setForeground:foreground];
		if ([interpreter working])
			{
			printf ("COWS Controller ERROR:  interpreter already working!\n");
			return NULL;
			}
		else 
			{
			if (autostart)		// load or load and run
				{
				[self _load];
				if (autostart==COWSCONTROLLER_AUTOLOADANDRUN) [self _run];
				}
			}
		}
	else
		{
		printf 
		    ("COWS Controller ERROR:  no interpreter to load and run!\n");
		return NULL;
		}
	return self;
	}

- start:sender
	{
	return [self awakeFromNib];
	}

- errorInterpreting:(int) thisError:(const char*)thisFunction:
	(int)thisPosition:(const char*)thisString:sender		
	{
	if (delegate&&[delegate conformsTo:@protocol(InterpreterToDelegate)])
		[delegate errorInterpreting:
			 thisError:thisFunction:thisPosition:thisString:sender];
	return self;
	}
	
- finishedInterpreting:(const char*)returnValue:(int)thisMessage:sender		
	{
	if (delegate&&[delegate conformsTo:@protocol(InterpreterToDelegate)])
		[delegate finishedInterpreting:returnValue:thisMessage:sender];
	return self;
	}
	
- interpreterStarted:sender
	{
	return self;
	}

- interpreterStopped:sender
	{
	if (delegate&&[delegate conformsTo:@protocol(InterpreterToDelegate)])
		[delegate interpreterStopped:sender];
	return self;
	}


- read:(NXTypedStream*) stream
	{
	char* o1;
	char* o2;
	char* o3;
	char* o4;
	char* o5;
	
	[super read:stream];
	NXReadTypes(stream,"*****",
		&o1,&o2,&o3,&o4,&o5);
	NXReadTypes(stream,"cccfi",
		&autostart,	
		&foreground,
		&locked,
		&timed_entry_speed,
		&pulses_per_timed_entry);
	
	if (o1) 
		{
		strcpy(initial_function,o1);
		free(o1);
		}
	if (o2)
		{
		strcpy(initial_arg1,o2);
		free(o2);
		}
	if (o3)
		{
		strcpy(initial_arg2,o3);
		free(o3);
		}
	if (o4)
		{
		strcpy(initial_arg3,o4);
		free(o4);
		}
	if (o5)
		{
		strcpy(initial_arg4,o5);
		free(o5);
		}
	return self;
	}

- write:(NXTypedStream*) stream
	{
	const char* o1=initial_function;
	const char* o2=initial_arg1;
	const char* o3=initial_arg2;
	const char* o4=initial_arg3;
	const char* o5=initial_arg4;
	
	[super write:stream];
	
	NXWriteTypes(stream,"*****",&o1,&o2,&o3,&o4,&o5);
	
	NXWriteTypes(stream,"cccfi",
		&autostart,	
		&foreground,
		&locked,
		&timed_entry_speed,
		&pulses_per_timed_entry);
	return self;
	}

@end