/* 
 * ToDoItemPublic - public implementation of ToDoItem, does not contain
 *		priority calculation code
 *
 * You may freely copy, distribute and reuse the code in this example.
 * This code is provided AS IS without warranty of any kind, expressed 
 * or implied, as to its fitness for any particular use.
 *
 * Copyright 1995 Ralph Zazula (rzazula@next.com).  All Rights Reserved.
 *
 */

#import "ToDoItemPublic.h"
#import <appkit/appkit.h>

@implementation ToDoItemPublic

static char *RZCopyStringBuffer(const char *s)
{
	return s ? NXCopyStringBuffer(s) : NULL;
}

static char *RZReplaceStringBuffer(char **s, const char *new)
{
	if(s && *s) {
		NX_FREE(*s);
		*s = NULL;
	}
	
	*s = RZCopyStringBuffer(new);
	
	return *s;
}

+ initialize
{
	if([self class] == [ToDoItemPublic class]) {
		[self setVersion:1];
	}
	return self;
}

- initSubject:(char *)subj startDate:(long)start dueDate:(long)due
	completeDate:(long)completed type:(char)type isPrivate:(BOOL)privateFlag
	isCompleted:(BOOL)completeFlag data:(char *)buf dataLen:(int)len
{
	if(self = [super init]) {
		RZReplaceStringBuffer(&subject, subj);
		
		startDate = start ? start : time(NULL);
		dueDate = due ? due : time(NULL)+60;
		dateCompleted = completed;
		
		_flags.type = type;
		_flags.private = privateFlag;
		_flags.completed = completeFlag;
		
		RZReplaceStringBuffer(&data, buf);
		dataLen = len;
		
	}
	return self;
}
	
- initFromItem:(id <ToDoItems>)anItem
{
	char *buf;
	int len;
	
	[anItem getData:&buf length:&len];
	
	return [self initSubject:[anItem subject] startDate:[anItem startDate]
				dueDate:[anItem dueDate] completeDate:[anItem dateCompleted]
				type:[anItem type] isPrivate:[anItem isPrivate]
				isCompleted:[anItem isCompleted] data:buf dataLen:len];
}

- init
{
	return [self notImplemented:_cmd];
}

- free
{
	if(subject) {
		NX_FREE(subject);
		subject = NULL;
	}
	if(data) {
		NX_FREE(data);
		data = NULL;
		dataLen = 0;
	}
	
	return [super free];
}

- (char *)subject						{ return subject; }
- (long)startDate						{ return startDate; }
- (long)dueDate						{ return dueDate; }
- (long)dateCompleted				{ return dateCompleted; }
- (char)type							{ return _flags.type; }
- (BOOL)isPrivate						{ return _flags.private; }
- (BOOL)isCompleted					{ return _flags.completed; }

- (const char *)asciiStartDate
{ 
	static char buf[40];
	
	if(!startDate) {
		return NULL;
	}
	
	strftime(buf, 40, "%m/%d/%y", localtime(&startDate));

	return buf;
}

- (const char *)asciiCompletedDate
{ 
	static char buf[40];
	
	if(!dateCompleted) {
		return NULL;
	}
	
	strftime(buf, 40, "%m/%d/%y", localtime(&dateCompleted));

	return buf;
}

- (const char *)asciiDueDate
{ 
	static char buf[40];
	
	switch(_flags.type) {
		case TODO_TYPE_NORMAL :
		case TODO_TYPE_APPOINTMENT :
			strftime(buf, 40, "%m/%d/%y", localtime(&dueDate));
			break;
		case TODO_TYPE_HIGHPRIORITY :
			sprintf(buf, "ASAP!");
			break;
		case TODO_TYPE_LOWPRIORITY :
			sprintf(buf, "LATER");
			break;
	}
	
	return buf;
}

- getData:(char **)d length:(int *)len
{
	*d = data;
	*len = dataLen;
	return self;
}
	
/*** archival methods ***/

- read:(NXTypedStream *)ts
{
	[super read:ts];
	
	switch(NXTypedStreamClassVersion(ts, [[self class] name])) {
		case 1 :
			NXReadTypes(ts, "*lll*iI",
				&subject, &startDate, &dueDate, &dateCompleted, 
				&data, &dataLen, _flags);
			break;	
	}
	
	return self;
}

- write:(NXTypedStream *)ts
{
	[super write:ts];
	NXWriteTypes(ts, "*lll*iI",
		&subject, &startDate, &dueDate, &dateCompleted, 
		&data, &dataLen, _flags);
	return self;
}

@end

@implementation ToDoItemPublic(Transport)

- encodeUsing:(id <NXEncoding>)stream
{
	[stream encodeData:&subject ofType:"*"];
	[stream encodeData:&startDate ofType:"l"];
	[stream encodeData:&dueDate ofType:"l"];
	[stream encodeData:&dateCompleted ofType:"l"];
	[stream encodeData:&data ofType:"*"];
	[stream encodeData:&dataLen ofType:"i"];
	[stream encodeData:&_flags ofType:"I"];
	return self;
}

- decodeUsing:(id <NXDecoding>)stream
{
	[stream decodeData:&subject ofType:"*"];
	[stream decodeData:&startDate ofType:"l"];
	[stream decodeData:&dueDate ofType:"l"];
	[stream decodeData:&dateCompleted ofType:"l"];
	[stream decodeData:&data ofType:"*"];
	[stream decodeData:&dataLen ofType:"i"];
	[stream decodeData:&_flags ofType:"I"];
	return self;
}

- encodeRemotelyFor:(NXConnection *)connection
    freeAfterEncoding:(BOOL *)flagp
    isBycopy:(BOOL)isBycopy
{
	if (isBycopy) {
		*flagp = YES;		// if bycopy, free the local instance
		return self;
	}

	// otherwise, super's behavior is to encode a proxy
   return [super encodeRemotelyFor:connection
		freeAfterEncoding:flagp
		isBycopy:isBycopy];
}

@end
