#include "wand_head.h"

#ifdef	MSDOS	/* M001	*/
#define	LOCK
#define	UNLOCK
#else
/*#define LOCK     flock( fp->_cnt , LOCK_EX ) /* peeked at stdio.h ! */
/*#define UNLOCK   flock( fp->_cnt , LOCK_UN ) /*                     */
#define LOCK while ((lock = creat(LOCKFILE,0))==-1)
#define UNLOCK unlink(LOCKFILE)
#endif

#ifndef	MSDOS	/* M001 */
extern int getuid();
#else
#define	 getuid()	0
#endif

extern int saved_game;  /* prevent recording of hiscore if  */
			/* NO_RESTORED_GAME_HISCORES is #def'd */

typedef struct {
    char howdead[25];
    char name[20];
    long score;
    int  level;
    int  uid;
} score_entry;

#ifdef	LINT_ARGS	/* M001	*/
void show_scores(score_entry *, int);
int readtable(score_entry *);
#else
void show_scores();
int readtable();
#endif

void show_scores(table, num)
score_entry *table;
int num;
{
    int tot = num;

    printf("\nNo. Score Level           Names                 How they died\n");
    printf("=============================================================================\n");
    while (num > 0) {
	num--;
	printf("%2d %5ld %3d      %-20s     killed by %-s\n",(tot - num),table->score,table->level,table->name,table->howdead);
	table++;
    }
    printf("\n\n");
}

int readtable(table_ptr)
score_entry *table_ptr;
{
    FILE *fp;
    int  numread;

    if ((fp = fopen(HISCOREPATH,R_BIN)) == NULL)
	numread = 0;
    else {
	numread = fread( VOIDSTAR table_ptr, sizeof(score_entry), ENTRIES, fp);
	fclose(fp);
    }
    return numread;
}

int savescore(howdead, score, level, name)
char *howdead, *name;
int  level;
long score;
{
    score_entry table[ENTRIES + 2],
	*table_ptr = table,new_entry,temp_entry;
    int  numread,index = 1, numsaved, lock, already = 0, output_value = 1,
	user_id, position;
    FILE *fp;
#ifdef NO_RESTORED_GAME_HISCORES
    if (saved_game) {
	printf("No hiscores recorded from restored games.\n");
	printf("\nWANDERER Copyright (C) 1988 S. Shipway.\n\n");
	return 1;
    }
#endif
    user_id = getuid();
    strncpy(new_entry.howdead,howdead,25);
    new_entry.howdead[24] = '\0';	/* M002 strncpy does not null terminate */
    strncpy(new_entry.name,name,20);
    new_entry.name[19] = '\0';	/* M002 strncpy does not null terminate */
    new_entry.score = score;
    new_entry.level = level;
    new_entry.uid = user_id;
    LOCK;
    numread = readtable(table_ptr);
    if (numread > 0)
	if(table[numread-1].score > 99999) {	/* stop system errors messing it up*/
	    numread--;
	    printf("Erasing spurious entry in table.\n");
	}
    if (score == -1) {
	show_scores(table,numread);
	UNLOCK;
	return 0;
    }
    if (numread > 0) {
	numread++;	/* scan through until correct insertion point */
	/* pass table entries with higher scores */
	while ((table_ptr->score > score)&&(index < numread)) {
#ifdef	COMPARE_BY_NAME
#define	SAMEUSER(p)	(strcmp((p)->name, name) == 0)
#else
#define	SAMEUSER(p)	((p)->uid == user_id)
#endif
	    if (SAMEUSER(table_ptr)) {
		already = 1;
		break;
	    }
	    table_ptr++;
	    index++;
	}
	/* pass table entries with equal score but higher or equal level */
	while ((table_ptr->level>=level) && (index<numread) &&
	    (table_ptr->score==score)) {
	    if (SAMEUSER(table_ptr)) {
		already = 1;
		break;
	    }
	    table_ptr++;
	    index++;
	}
	position = index;
	/* if already found: done */
	if (already == 1) {
	    numread--;
	    UNLOCK;
	    return numread;
	}
	/* shift down score list */
	while (index < numread) {
	    /* swap *table_ptr and new_entry */
	    temp_entry = *table_ptr;
	    *table_ptr = new_entry;
	    new_entry = temp_entry;
	    if (SAMEUSER(&new_entry)) {
		already = 1;
		numread--;	/* an older entry found */
		break;
	    }
	    table_ptr++;
	    index++;
	}
	/* if all shifted without finding an older entry */
	if (already == 0)
	    *table_ptr = new_entry;
	if (position <= ENTRIES)
	    printf("You rank %d in the hiscore table.\n",position);
	else
	    printf("Sorry, you didn't make it into the hiscore table this time.\n");
    } else {
	printf("\nCreating new hiscore table.\n\n");
	*table_ptr = new_entry;
	numread++;
    }
    numread = ((numread > ENTRIES) ? ENTRIES : numread);
    fp = fopen(HISCOREPATH,W_BIN);
    table_ptr = table;
    numsaved = fwrite( VOIDSTAR table_ptr, sizeof(score_entry), numread, fp);
    chmod(HISCOREPATH,0666);
    if (numsaved < numread) {
	printf("ERROR! Only %d items saved from %d !\n",numsaved,numread);
	output_value = 0;
    }
    fclose(fp);
    UNLOCK;
    return output_value;
}

void delete_entry(num)
int num;
{
    score_entry table[ENTRIES + 22],
	*table_ptr = table,
	new_entry,temp_entry;
    int  numread,index = 1, numsaved, lock, output_value = 1;
    FILE *fp;
    LOCK;
    numread = readtable(table_ptr);
    if (numread == 0) {
	printf("Missing or unreadable hiscore table.\n\n");
	UNLOCK;
	exit(1);
    }
    if (num > numread) {
	printf("Invalid entry, choose again\n");
	UNLOCK;
	return;
    }
    while (index < num) {
	index++;
	table_ptr++;
    }
    while (index < numread) {
	index++;
	*table_ptr = *(table_ptr+1);
	table_ptr++;
    }
    numread--;
    fp = fopen(HISCOREPATH,W_BIN);
    table_ptr = table;
    numsaved = fwrite(VOIDSTAR table_ptr, sizeof(score_entry), numread, fp);
    chmod(HISCOREPATH,0666);
    if (numsaved < numread) {
	printf("ERROR! Only %d items saved from %d !\n",numsaved,numread);
	output_value = 0;
    }
    fclose(fp);
    UNLOCK;
    show_scores(table,numsaved);
}

erase_scores()
{
    int erasenum, numread, index = 0;
    char correct[20], c;
    score_entry table[ENTRIES + 2],
	*table_ptr = table;

    printf("Please enter password:");
    while ((c = getchar()) != '\n' && index <19)
	correct[index++] = c;
    correct[index] = 0;
    if (strcmp(correct,MASTERPASSWORD)) {
	printf("\nFoo, charlatan!\n");
	return 0;
    }
    numread = readtable(table_ptr);
    show_scores(table,numread);
    printf("\n");
    for(;;) {
	printf("Number to erase (0 to exit): ");
	scanf("%d",&erasenum);
	printf("\n");
	if (erasenum == 0)
	    break;
	delete_entry(erasenum);
	printf("\n");
    }
    printf("Byee!\n");
}
