// 

#import "HighScoreTable.h"

// 8/26/93	init: strcpy(defaultPlayerName,NXUserName()); by cat
// 8/26/93	NXBundle support; by cat

//#import "PreferencesBrain.h"
//#import "GameBrain.h"

#import <appkit/appkit.h>

@implementation HighScoreTable

- init		// designated initializer sets up game variables
{		// to sensible values.
    int i;

    for (i=0; i<MAXSCORES; i++) {  // get space to store names of high scorers
    	highNames[i] = malloc(256);
    }
    
    if( !highScorePanel)
      [NXApp loadNibSection:"HighScore.nib" owner:self withNames:NO];
    
    defaultPlayerName = malloc(64);
    strcpy(defaultPlayerName,NXUserName());
    scoreFileName = malloc(strlen(NXArgv[0]) + 16);
    
    // get name of highscore file (inside app wrapper)
    
	if(NO == 
	[[NXBundle mainBundle] getPath:scoreFileName forResource:"highscores" ofType:""])
	{	*scoreFileName = 0;
		[self writeHighScores];
	}
	
    [self readHighScores];
    
    return self;
}

/* methods to get at important variables */
- highScorePanel { return highScorePanel; }
- setHighScorePanel:(id)panel { highScorePanel = panel; return self; }
- highScoreDispMatrix { return highScoreDispMatrix; }
- setHighScoreDispMatrix:(id)matrix {highScoreDispMatrix=matrix; return self;}
- (int)highScore:(int)num { return highScores[num]; }
- (const char *)defaultPlayerName { return defaultPlayerName; }

- setDefaultPlayerName:(const char *)name
{
    strcpy(defaultPlayerName,name);
    return self;
}

- findHighScoreText:sender		// used by below method to update cells
{
    int tag = [sender tag];
    
    if ((tag % 2) == 0) {	// name
    	[sender setStringValue:highNames[tag / 2]];
    } else {			// score
    	[sender setIntValue:highScores[tag / 2]];
    }
    return self;
}

- showHighScores			// update display matrix
{
    return [highScoreDispMatrix sendAction:@selector(findHighScoreText:)
    		to:self forAllCells:YES];
}

- zeroHighScores			// wipes out high scores
{
    int i;
    char *tempStr;
    
    for (i=0; i<MAXSCORES; i++) {
        highScores[i] = (MAXSCORES - i) * 100;
	tempStr = malloc(16);
	sprintf(tempStr, "Nobody #%d", i + 1);
	strcpy(highNames[i], tempStr);
	free(tempStr);
    }
    [self showHighScores];
    return self;
}

- putInHighScores:(int)score  // put player in high score table if applicable
{
    int i, j;
    id nameText;
    
    if( !highScorePanel)
      [self init];

    for (i=0; i<MAXSCORES; i++) {
		if (score >= highScores[i]) break;
	}
    if (i == MAXSCORES) {
		[self displayHighScores:self]; // high score panel out
		return self; // not a new high score
	}
	for (j=9; j>i; j--) { // shift old scores down
		strcpy(highNames[j],highNames[j-1]);
		highScores[j] = highScores[j-1];
    }
	highScores[i] = score;
	strcpy(highNames[i], defaultPlayerName);
	// set up textfield to accept player's name
	if (highCell != nil) { // still hasn't entered previous name, so lost
		// the chance -- we put in default now.
		[highCell setBackgroundGray:NX_LTGRAY];
		[highCell setBezeled:NO];
		[highCell setEditable:NO];
		highCell = nil;
	}
	nameText = [highScoreDispMatrix findCellWithTag:i*2];
	[nameText setBackgroundGray:NX_WHITE];
	[nameText setEditable:YES];
	[nameText setBezeled:YES];
	[nameText setStringValue:highNames[i]];
	highCell = nameText;
    
    [self showHighScores];  // update matrix (like doing displayHighScores:)
	[highScorePanel makeKeyAndOrderFront:self];  // want user to enter name
    [highScoreDispMatrix selectCellWithTag:i*2]; 
    return self;
}

- displayHighScores:sender 	// bring up high scores w/info loaded into it
{
    if( !highScorePanel)
      [self init];
    [self showHighScores];
    [highScorePanel orderFront:self];
    return self;
}

- readHighScores			// read scores from file 
{
    NXTypedStream *typedStream;
    int i; char *tmpStr;

    [self zeroHighScores];

    typedStream = NXOpenTypedStreamForFile(scoreFileName, NX_READONLY);
	if (typedStream == NULL) {
		NXRunAlertPanel("readHighScores","No highscore file.",NULL,NULL,"OK");
		return self;
	}
    for (i=0; i<MAXSCORES; i++) {
		NXReadTypes(typedStream, "i*", &highScores[i], &tmpStr);
		strcpy(highNames[i], tmpStr);
    }
	NXCloseTypedStream(typedStream);

    return self;
}

- writeHighScores			// write scores to file 
{
	NXStream*	  stream;
	NXTypedStream *typedStream;
	int i;

	if(*scoreFileName == 0)
	{	strcpy(scoreFileName,[[NXBundle mainBundle] directory]);
		strcat(scoreFileName,"/highscores");
		[self zeroHighScores];
	}
	
	stream = NXMapFile(scoreFileName,NX_WRITEONLY);
	if (!stream) 
		stream = NXOpenMemory(0,0,NX_WRITEONLY);
	
	typedStream = NXOpenTypedStream(stream,NX_WRITEONLY);
	for (i=0; i<MAXSCORES; i++)
		NXWriteTypes(typedStream, "i*", &highScores[i], &highNames[i]);
	
	NXCloseTypedStream(typedStream);
	if(-1 == NXSaveToFile(stream,scoreFileName))
	{	NXRunAlertPanel("High Scores",
		"Cannot save high scores. Check path & permissions to:\n%s",0,0,0,scoreFileName);
		return [self free];
	}

	NXCloseMemory(stream,NX_FREEBUFFER);
	
	return self;
}

- clearHighScores:sender	// zeroes the high scores -- IB method
{
	[self zeroHighScores];
	[self showHighScores]; // make game brain update "high score" field
	return [self writeHighScores];
}

- acceptHighScore:sender	// accept name into high score table - sent by
{				// name matrix when user fills in his/her name
    int i;
    
    if (highCell != nil) { // should always be true, but check just in case
		i = [highCell tag]/2;
		strcpy(highNames[i], [highCell stringValue]);
		strcpy(defaultPlayerName, highNames[i]);
		//[preferences setDefaultPlayerName:defaultPlayerName];
		[highCell setBackgroundGray:NX_LTGRAY];
		[highCell setEditable:NO];
		[highCell setBezeled:NO];
		highCell = nil;
	}
	[self writeHighScores];	// be sure that highscore file is updated
	//[gameWindow makeKeyAndOrderFront:self];
	return self;
}

@end
