// Copyright 1994 Brad Pitzel
//
// Feel free to use/distribute/modify as long as credit/copyrights for myself 
// are included.

// File   : HiScore.c[1.0]
// Name   : gamelib1.0
// Status : proposed
// Changed: Sun Jun 12 22:19:14 1994


#include "HiScore.h"
#include <fstream.h>


// pad a string out on the right to at least 'len' chars
void rPad(String &str, int len)
   {
   // messy, but I can't see from Gnu's String class how to initialize
   // a string to a given length, eg  String(' ',20) would be nice...
   while (str.length()<len)
   	str += "          ";
   	
   str = str(0,len);
   }

// create hi score list: read in from save file if it exists
// Note: no error checking on format of save file!
HiScore::HiScore( const char *file )
	{
	Vfile = file;

	// init list
	int i;
	for (i=0; i<HiScoreListSize; i++)
		{
		Vscore[i] = 0;
		rPad( Vname[i], MaxNameLength );
		}

	FILE *fp;
	fp = fopen(Vfile,"r");
	
	if (fp!=NULL)
		{
		// the first byte should be a 0
		char c;
		fread(&c, sizeof(c), 1, fp);
		
		if (c!=0)
			{
			cout << "Note: old style high score file found." << endl;
			cout << "(Don't worry, it will be updated)" << endl;
			fclose(fp);
			readOldFormat();
			}
		else
			{
			i=0;
			while (!feof(fp)&&(i<HiScoreListSize))
				{
				// note following double casts -- see str.h
				// for the reason why :-)
				fread( (char *)(const char *)Vname[i], 
				       MaxNameLength, 1, fp);
				       
				fread( &(Vscore[i]), sizeof(Score), 1, fp);
				i++;
				}
			fclose(fp);
			}
		} // fp!=NULL	
	}


// save hi score list on destruction
HiScore::~HiScore()
	{
	save();
	}

// Read in a high score file in the old text format.
void HiScore::readOldFormat()	
	{
	// if file exists, load high scores/names into memory
	ifstream ifstr(Vfile);
	
	if (ifstr.is_open())
		{
		int i=0;
		
		while( (i<HiScoreListSize) && (!ifstr.eof()) )
			{
			ifstr >> Vname[i] >> Vscore[i];
			i++;
			}
			
		ifstr.close();
		}
	}
	

// return pos 0..(ListSize-1) if score is good enough, -1 otherwise
char HiScore::isHigh( Score s ) const
	{
	char result=-1;
	int i=0;
	
	while( (i<HiScoreListSize) && (result==-1) )
		{
		if (Vscore[i]<s) result=i;
		else i++;
		}
		
	return result;
	}

char HiScore::add( const char *name, Score s )
	{
	char result = 0;
	char pos = isHigh( s );
	int  i;
	
	if (pos >= 0 )
		{
		// move everyone below down 1 position in list
		for(i=(HiScoreListSize-1); i>pos; i--)
			{
			Vscore[i] = Vscore[i-1];
			Vname[i]  = Vname[i-1];
			}
		
		Vscore[pos] = s;
		Vname[pos] = name;

		result = 1;
		}
	return result;
	}


// save high score list to file
char HiScore::save()
	{
	char result = EXIT_FAILURE;

	FILE *fp = fopen(Vfile,"w");
	
	if (fp!=NULL)
		{
		// lay down 1st byte to indicate this is the new style
		// of highscore file.
		char c=0;
		fwrite(&c, sizeof(c), 1, fp);
		
		int i=0;
		
		while( (i<HiScoreListSize) )
			{
			rPad( Vname[i], MaxNameLength );
			
			fwrite( (char *)(const char *)Vname[i], 
				MaxNameLength, 1, fp);
				
			fwrite( &(Vscore[i]), sizeof(Score), 1, fp);
			i++;
			}

		fclose(fp);
		result = EXIT_SUCCESS;
		}
	else
		{
		perror("Cannot open score file for writing");
		}

	return result;
	}
