// GameInfo.m -- This object allows you to set global parameters that
// 		affect the GameKit in various ways.

#import <gamekit/gamekit.h>
#import <daymisckit/daymisckit.h>
#import <appkit/appkit.h>

@implementation GameInfo

- init	// implement to generate an empty slot for server
{
	int i;
	[super init];
	maxHighScores = 10; numHighScoreTables = 1; numSoundStreams = 1;
	numSounds = GK_DEFNUMSOUNDS; numSoundTypes = GK_DEFNUMTYPES;
	numOneUps = 3;
	// this object assumes that this array is allocated.  Don't use the
	// object if it isn't or you'll get memory access exceptions (probably
	// on address 0x0)
	maxHighScoresPerPlayer = (int *)malloc(sizeof(int) *
			2 * numHighScoreTables);
	for (i=0; i<(numHighScoreTables * 2); i++) maxHighScoresPerPlayer[i] = 0;
	slotType = [[DAYString alloc] initString:"HighScoreSlot"];
	encryptedPassword = [[DAYString alloc] initString:"GK72ol87WD.CE"];
		// the above password is "NONE".  Override with your own.
	return self;
}

- free
{	// free all the sub-objects.
	[slotType free];
	[encryptedPassword free];
	if (maxHighScoresPerPlayer) free(maxHighScoresPerPlayer);
	return self;
}

- dumpToLog:aLogFile	// used by server when logging
{	// aLogFile must be a kind of the DAYLogFile class
	char *string = (char *)malloc(256); int i;
	id tempString = [[DAYString alloc] init];
	sprintf(string, "    numSounds = %d\n    numSoundTypes = %d\n    numSoundStreams = %d\n    maxHighScores = %d\n    numHighScoreTables = %d\n    numOneUps = %d\n    slotType = \"%s\"\n    encryptedPassword = \"%s\"\n",
			numSounds, numSoundTypes, numSoundStreams,
			maxHighScores, numHighScoreTables, numOneUps,
			[slotType stringValue], [encryptedPassword stringValue]);
	[tempString setStringValue:string];
	[aLogFile addLineToLogFile:tempString];
	for (i=0; i<numHighScoreTables; i++) {
		sprintf(string, "        maxHighScoresPerPlayer for table %d (net = NO) = %d\n        maxHighScoresPerPlayer for table %d (net = YES) = %d\n",
				i, maxHighScoresPerPlayer[i*2],
				i, maxHighScoresPerPlayer[i*2+1]);
		[tempString setStringValue:string];
		[aLogFile addLineToLogFile:tempString];
	}
	free(string);
	[tempString free];
	return self;
}

// The following methods access stored info.
- slotType			// For the high score system
{
	return slotType;
}

- (int)numOneUps				// for the high score system
{
	return numOneUps;
}

- (int)maxHighScores				// for the high score system
{
	return maxHighScores;
}

- (int)numHighScoreTables	// for the high score system
{
	return numHighScoreTables;
}

- encryptedPassword	// For network high score table access
{
	return encryptedPassword;
}

- (int)numSounds			// for the sound system
{
	return numSounds;
}

- (int)numSoundTypes		// for the sound system
{
	return numSoundTypes;
}

- (int)numSoundStreams		// for the sound system
{
	return numSoundStreams;
}


// The following methods change stored info.  All return self.
- setnumSoundTypes:(int)anInt
{
	numSoundTypes = anInt;
	return self;
}

- setnumSoundStreams:(int)anInt
{
	numSoundStreams = anInt;
	return self;
}

- setnumSounds:(int)anInt
{
	numSounds = anInt;
	return self;
}

- setnumHighScoreTables:(int)anInt
{ // copy over the max scores per player and reallocate it to the right size
	int i, *newMaxScores = (int *)malloc(sizeof(int) * 2 * anInt);
	for (i=0; i<anInt; i++) { // return zero if out of range...
		// if you compile with NOISYDEBUG, you'll see a mass of "errors"
		// every time this array is enlarged.  Ignore them; it's on purpose!
		newMaxScores[i*2] = [self maxScoresPerPlayerTable:i net:0];
		newMaxScores[i*2+1] = [self maxScoresPerPlayerTable:i net:1];
	}
	free(maxHighScoresPerPlayer);
	maxHighScoresPerPlayer = newMaxScores;
	numHighScoreTables = anInt;
	return self;
}

- setMaxHighScores:(int)anInt
{
	maxHighScores = anInt;
	return self;
}

- setSlotType:(const char *)aString
{
	[slotType setStringValue:aString];
	return self;
}

- setEncryptedPassword:(const char *)aString
{
	[encryptedPassword setStringValue:aString];
	return self;
}

- setNumOneUps:(int)oneUps
{
	numOneUps = oneUps;
	return self;
}

- (int)maxScoresPerPlayerTable:(int)theTable net:(BOOL)which
{
	if ((theTable >= numHighScoreTables) || (theTable < 0)) {
#ifdef NOISYDEBUG
		fprintf(stderr,
			"GameInfo:  Table arg (%d) to -maxScoresPerPlayerTable:net: out of range.\n",
			theTable);
#endif
		return 0;  // out of range
	}
	return maxHighScoresPerPlayer[theTable * 2 + (which ? 1 : 0)];
}

- setMaxScoresPerPlayerTable:(int)theTable net:(BOOL)which to:(int)val
{
	if ((theTable >= numHighScoreTables) || (theTable < 0)) {
#ifdef NOISYDEBUG
		fprintf(stderr,
			"GameInfo:  Table arg (%d) to -setMaxScoresPerPlayerTable:net:to: out of range.\n",
			theTable);
#endif
		return nil;  // out of range
	}
	maxHighScoresPerPlayer[theTable * 2 + (which ? 1 : 0)] = val;
	return self;
}

// for archiving to/from a file
- read:(NXTypedStream *)stream
{
	int i;
	[super read:stream];
	NXReadTypes(stream, "iiiiii", &maxHighScores, &numHighScoreTables,
			&numSounds, &numSoundTypes, &numSoundStreams, &numOneUps);
	slotType = NXReadObject(stream);
	encryptedPassword = NXReadObject(stream);
	if (maxHighScoresPerPlayer)	free(maxHighScoresPerPlayer);
	maxHighScoresPerPlayer = (int *)malloc(sizeof(int) *
		2 * numHighScoreTables);
	for (i=0; i<(numHighScoreTables * 2); i++)
		NXReadType(stream, "i", &maxHighScoresPerPlayer[i]);
#ifdef NOISYDEBUG
	fprintf(stderr,
			"GameInfo:  -read:\n    maxHighScores = %d\n", maxHighScores);
	fprintf(stderr, "    numHighScoreTables = %d\n", numHighScoreTables);
	fprintf(stderr, "    numSounds = %d\n", numSounds);
	fprintf(stderr, "    numSoundTypes = %d\n", numSoundTypes);
	fprintf(stderr, "    numSoundStreams = %d\n", numSoundStreams);
	fprintf(stderr, "    numOneUps = %d\n", numOneUps);
	fprintf(stderr, "    slotType = %s\n", [slotType stringValue]);
	fprintf(stderr, "    encryptedPassword = %s\n",
			[encryptedPassword stringValue]);
	for (i=0; i<(numHighScoreTables * 2); i++)
		fprintf(stderr, "    maxHighScoresPerPlayer[%d] = %d\n",
				i, maxHighScoresPerPlayer[i]);
	fprintf(stderr, "\n");
#endif
	return self;
}

- write:(NXTypedStream *)stream
{
	int i;
	[super write:stream];
#ifdef NOISYDEBUG
	fprintf(stderr,
			"GameInfo:  -write:\n    maxHighScores = %d\n", maxHighScores);
	fprintf(stderr, "    numHighScoreTables = %d\n", numHighScoreTables);
	fprintf(stderr, "    numSounds = %d\n", numSounds);
	fprintf(stderr, "    numSoundTypes = %d\n", numSoundTypes);
	fprintf(stderr, "    numSoundStreams = %d\n", numSoundStreams);
	fprintf(stderr, "    numOneUps = %d\n", numOneUps);
	fprintf(stderr, "    slotType = %s\n", [slotType stringValue]);
	fprintf(stderr, "    encryptedPassword = %s\n",
			[encryptedPassword stringValue]);
	for (i=0; i<(numHighScoreTables * 2); i++)
		fprintf(stderr, "    maxHighScoresPerPlayer[%d] = %d\n",
				i, maxHighScoresPerPlayer[i]);
	fprintf(stderr, "\n");
#endif
	NXWriteTypes(stream, "iiiiii", &maxHighScores, &numHighScoreTables,
			&numSounds, &numSoundTypes, &numSoundStreams, &numOneUps);
	NXWriteObject(stream, slotType);
	NXWriteObject(stream, encryptedPassword);
	for (i=0; i<(numHighScoreTables * 2); i++)
		NXWriteType(stream, "i", &maxHighScoresPerPlayer[i]);
	return self;
}

// NXTransport protocol implementation:
- encodeUsing:(id <NXEncoding>)portal
{
	int i;
	[portal encodeObjectBycopy:slotType];
	[portal encodeObjectBycopy:encryptedPassword];
	[portal encodeData:&maxHighScores ofType:"i"];
	[portal encodeData:&numHighScoreTables ofType:"i"];
	[portal encodeData:&numSounds ofType:"i"];
	[portal encodeData:&numSoundTypes ofType:"i"];
	[portal encodeData:&numSoundStreams ofType:"i"];
	[portal encodeData:&numOneUps ofType:"i"];
	for (i=0; i<(numHighScoreTables*2); i++)
		[portal encodeData:&maxHighScoresPerPlayer[i] ofType:"i"];
	return self;
}

- decodeUsing:(id <NXDecoding>)portal
{
	int i;
	slotType = [portal decodeObject];
	encryptedPassword = [portal decodeObject];
	[portal decodeData:&maxHighScores ofType:"i"];
	[portal decodeData:&numHighScoreTables ofType:"i"];
	[portal decodeData:&numSounds ofType:"i"];
	[portal decodeData:&numSoundTypes ofType:"i"];
	[portal decodeData:&numSoundStreams ofType:"i"];
	[portal decodeData:&numOneUps ofType:"i"];
	if (maxHighScoresPerPlayer) free(maxHighScoresPerPlayer);
	maxHighScoresPerPlayer = (int *)malloc(sizeof(int) *
		2 * numHighScoreTables);
	for (i=0; i<(numHighScoreTables*2); i++)
		[portal decodeData:&maxHighScoresPerPlayer[i] ofType:"i"];
	return self;
}

- encodeRemotelyFor:(NXConnection *)connection
	freeAfterEncoding:(BOOL *)flagp isBycopy:(BOOL)isByCopy
{
	if (isByCopy) return self; //encode object (copy it)
	// super will encode the proxy otherwise
	return [super encodeRemotelyFor:connection
				freeAfterEncoding:flagp isBycopy:isByCopy];
}

// Interface Builder support
- (const char *)getInspectorClassName { return "GameInfoInspector"; }
- (NXImage *)getIBImage { return [NXImage findImageNamed:"GameInfoObj"]; }

@end
