/*
 *  Copyright (C) 1993  Robert Davis
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of Version 2, or any later version, of 
 *  the GNU General Public License as published by the Free Software 
 *  Foundation.
 */

static char RCSId[]="$Id: DoubleValueSortedList.m,v 1.5 1993/05/04 16:21:46 davis Exp $";


#import "DoubleValueSortedList.h"
#import "TicObject.h"

@implementation DoubleValueSortedList


- init
{
    [super init];
    isAscending = YES;
    absoluteMax = NO_MAX;

    return self;
}


- setAscending:(BOOL)aBool
{
    isAscending = aBool;
    [self _reorderObjects];
    return self;
}


- (BOOL) isAscending
{
    return isAscending;
}


- setMax:(int)anInt
{
    if ((anInt > 0) || (anInt == NO_MAX))
	absoluteMax = anInt;

    return self;
}


- (int)max
{
    return absoluteMax;
}


/* 
 * Returns location of the added object -- the index where it was 
 * inserted.  It is currently impossible to tell if the object was 
 * successfully added.  This could be fixed.
 */
- (int)addObject:anObject
{
    if (anObject && ((absoluteMax == NO_MAX) || (numElements < absoluteMax))) {
	double value;
	int count;

	/*  
	 *  Get the sort value of the object and insert it at the 
	 *  correct place in the list.
	 */

	value = [anObject doubleValue];
	for (count = 0 ; count < numElements ; count++) {
	    switch (isAscending) {
	    case YES:
		if ([[self objectAt:count] doubleValue] > value) {
		    [super insertObject:anObject at:count];
		    return count;
		}
		break;
	    case NO:
		if ([[self objectAt:count] doubleValue] < value) {
		    [super insertObject:anObject at:count];
		    return count;
		}
		break;
	    }
	}

	[super insertObject:anObject at:numElements];
	return numElements - 1;
    }

    return NX_NOT_IN_LIST;
}


- (int)addObjectIfDoubleAbsent:anObject
{
    if (anObject && ((absoluteMax == NO_MAX) || (numElements < absoluteMax))) {
	double value;
	int count;

	value = [anObject doubleValue];
	for (count = 0; count < numElements; count++) {
	    double existing;

	    switch (isAscending) {
	    case YES:
		if ((existing = [[self objectAt:count] doubleValue]) == value)
		    return NX_NOT_IN_LIST;
		else if (existing > value) {
		    [super insertObject:anObject at:count];
		    return count;
		}
		break;
	    case NO:
		if ((existing = [[self objectAt:count] doubleValue]) == value)
		    return NX_NOT_IN_LIST;
		else if (existing < value) {
		    [super insertObject:anObject at:count];
		    return count;
		}
		break;
	    }
	}

	[super insertObject:anObject at:numElements];
	return numElements - 1;
    }

    return NX_NOT_IN_LIST;
}


/** Overridden to do nothing **/

- insertObject:anObject at:(unsigned)index
{
    return nil;
}


- replaceObjectAt:(unsigned) index with:newObject
{
    return nil;
}



/** Private methods **/

- _reorderObjects
{
    int count;
    BOOL done = NO;

    if (!numElements || (numElements == 1))
	return self;


    /*  Do a simple bubble sort (the list is assumed to be fairly small). */

    while (!done) {
	done = YES;
	for (count = 0 ; count < (numElements - 1) ; count++) {
	    switch (isAscending) {
	    case YES:
		if ([[self objectAt:count] doubleValue] > 
		    [[self objectAt:count + 1] doubleValue]) {    /* Swap */
		    [super insertObject:[self removeObjectAt:count]
				     at:count + 1];
		    done = NO;
		}
		break;
	    case NO:
		if ([[self objectAt:count] doubleValue] < 
		    [[self objectAt:count + 1] doubleValue]) {    /* Swap */
		    [super insertObject:[self removeObjectAt:count]
				     at:count + 1];
		    done = NO;
		}
		break;
	    }
	}
    }

    return self;
}


// Shuts up the compiler about unused RCSId
- (const char *) rcsid
{
    return RCSId;
}


@end
