/* SortedStorage.m
 * Written By:  Thomas Burkholder
 *
 * You may freely copy, distribute, and reuse the code in this example.
 * NeXT disclaims any warranty of any kind, expressed or  implied, as to its
 * fitness for any particular use.
 */

#import "SortedStorage.h"

@implementation SortedStorage:Storage

- initCount:(unsigned)count elementSize:(unsigned)sizeInBytes description:(const char *)descriptor
{
	[super initCount:count elementSize:sizeInBytes description:descriptor];
	agent = nil;
	return self;
}

- setAgent:anObject
{
	agent = anObject;
	return self;
}

- agent
{
	return agent;
}

- (id)subdirectoryForElementAt:(int)at
{
	return [agent subdirectoryFor:[self elementAt:at] sender:self];
}

- (BOOL)isLeafAt:(int)at
{
	return [agent isLeaf:[self elementAt:at] sender:self];
}

- (const char *)displayStringForElementAt:(int)at
{
	return [agent displayStringFor:[self elementAt:at] sender:self];
}

- (int)compareElementAt:(int)at with:(void *)anElement
{
	return [agent compare:[self elementAt:at] with:anElement sender:self];
}

- (int)browser:sender fillMatrix:matrix inColumn:(int)column
{
	id c;
	int i,n;
	id candidate = self;

	if (column != 0) {
		for(i=0;(i<column);i++) {
			candidate = [candidate subdirectoryForElementAt:[[sender matrixInColumn:i] selectedRow]];
			if ((!candidate) || (![candidate isKindOf:[SortedStorage class]])) return 0;
		}
	}

	for(i=0,n=[candidate count];i<n;i++) {
		[matrix addRow];
		c = [matrix cellAt:i :0];
		[c setLeaf:[candidate isLeafAt:i]];
		[c setLoaded:YES];
		[c setStringValue:[candidate displayStringForElementAt:i]];
	}
	return i;
}

- (const char *)browser:sender titleOfColumn:(int)column
{
	return [agent titleOfColumn:column];
}

- binaryInsert:(void *)anElement between:(int)lower and:(int)upper
{
	int r,c = lower + (1+upper-lower)/2;

	if (lower == upper) {  
		if ([self compareElementAt:lower with:anElement]>0) //insert before
			return [self insertElement:anElement at:lower];
		else  // insert after
			return [self insertElement:anElement at:lower+1];
	}

	r = [self compareElementAt:c with:anElement];
	if (r>0)  // Recursion is Good.
		return [self binaryInsert:anElement between:lower and:c-1];
	else if (r<0)  // In fact, Recursion is Holy.
		return [self binaryInsert:anElement between:c and:upper];
	else  // if equal insert right now.
		return [self insertElement:anElement at:c];
}

- addElement:(void *)anElement
{
	// Binary insertion...
	if (![self count])
		return [super addElement:anElement];
	[self binaryInsert:anElement between:0 and:[self count]-1];
	return self;
}

- read:(NXTypedStream *)stream
{
	[super read:stream];
	agent = NXReadObject(stream);
	return self;
}

- write:(NXTypedStream *)stream
{
	[super write:stream];
	NXWriteObject(stream,agent);
	return self;
}

@end