/***************************************************************************
                          hiscore.cpp  -  description
                             -------------------
    begin                : Wed Mar 1 2000
    copyright            : (C) 2000 by Michael Speck
    email                : 
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "hiscore.h"


#ifdef __riscos__
char *hi_dir = getenv("HOME");
#else
char *hi_dir = HI_DIR;
#endif



// CompositeHiScore
// ------------------------------------------------------

CompositeHiScore::CompositeHiScore(char* f)
{
  pLevel = NULL;
  pStandard = NULL;

  /*ARB: 21 May 2003: Always set up filename so a new table
    is written if one doesn't exist.
  strcpy(filename, "");
  char path[strlen(hi_dir) + strlen(f) + 1];
  sprintf(path, "%s%s", hi_dir, f);
  */
  sprintf(filename,"%s/%s",hi_dir, f);

  FILE *file = fopen(filename, "r");
  if (file == 0) {
    printf("cannot read '%s': permission denied...\n", filename);
    pStandard = new StandardHiScore((FILE*)0);
    pLevel = new LevelHiScore((FILE*)0);
    return;
  }
//  strcpy(filename,path);
  pStandard = new StandardHiScore(file);
  pLevel = new LevelHiScore(file);
  fclose(file);
}

CompositeHiScore::~CompositeHiScore() 
{
  delete pStandard;
  delete pLevel;
}

void CompositeHiScore::Save() 
{
  FILE *file = fopen(filename,"w");
  if (file == 0) {
    printf("cannot write '%s': permission denied...\n", filename);
    return;
  }
  pStandard->Save(file);
  pLevel->Save(file);
  fclose(file);
}

void CompositeHiScore::Save(char* f) {
 FILE *file = fopen(f,"w");
  if (file == 0) {
    printf("cannot write '%s': permission denied...\n", f);
    return;
  }
  pStandard->Save(file);
  pLevel->Save(file);
  fclose(file);
}

int CompositeHiScore::Load(char* f) {
 FILE *file = fopen(f,"r");
  if (file == 0) {
    printf("cannot read '%s': permission denied...\n", f);
    return -1;
  }
  pStandard->Load(file);
  int x = pLevel->Load(file);
  fclose(file);
  return 0;
}

HiScoreEntry CompositeHiScore::Entry(int line, int table/*=0*/)
{
  if (0==table) return pStandard->Entry(line);
  else if (1==table) return pLevel->Entry(line);
  else {
    printf("Bug!\n");
    return pLevel->Entry(line);
  }
}

int CompositeHiScore::CheckEntry(HiScoreEntry *entry) {
  int level0 = pStandard->CheckEntry(entry);
  int level1 =  pLevel->CheckEntry(entry);
  return (10*level1+level0);
}


// LevelHiScore
// ------------------------------------------------------

int LevelHiScore::CheckEntry(HiScoreEntry *entry)
{
	for (int i = 0; i < entry_num; i++)
		if (entry->level > entries[i].level || (entry->level == entries[i].level && entry->score >= entries[i].score)) {
			//found
			for (int j = entry_num - 1; j > i; j--)
				entries[j] = entries[j - 1];
			entries[i] = *entry;
			return i+1;
		}
		
	return 0;
}


// StandardHiScore
// ------------------------------------------------------
StandardHiScore::StandardHiScore(char *f) 
{
	strcpy(filename, "");
	entry_num = 0;
	entries = 0;
	if (Load(f)) Create();
}

StandardHiScore::StandardHiScore(FILE *f) 
{
	strcpy(filename, "");
	entry_num = 0;
	entries = 0;
	if (!f || Load(f)) Create();
}

StandardHiScore::~StandardHiScore()
{
	if (entries) delete entries;
}

// HiScore interface
// ------------------------------------------------------

HiScore* HiScore::CreateStandard(char* fileName)
{
  return new StandardHiScore(fileName);
}

HiScore* HiScore::CreateLevel(char* fileName) 
{
  return new LevelHiScore(fileName);
}

HiScore* HiScore::CreateComposite(char* fileName)
{
  return new CompositeHiScore(fileName);
}



HiScore::~HiScore() {}

void StandardHiScore::Create()
{
	entry_num = 10;
	if (entries) delete entries;
	entries = new HiScoreEntry[entry_num];
	for (int i = 0; i < entry_num; i++) {
		entries[i].level = 0;
		entries[i].score = 0;
		entries[i].lives = 0;
		strcpy(entries[i].name, "<empty>");
	}
}

int StandardHiScore::Load(char *f)
{
   	char path[strlen(hi_dir)+ strlen(f) + 1];
    sprintf(path, "%s%s", hi_dir, f);
	FILE *file = fopen(path, "r");
	if (file == 0) {
	    printf("hiscore '%s' not found...\n", path);
    	strcpy(filename, f);
	    return 1;
	}
	
	Load(file);
	fclose(file);
	strcpy(filename, f);
	return 0;
}

int StandardHiScore::Load(FILE* file) 
{
	fread(&entry_num, sizeof(int), 1, file);
	if (entries) delete entries;
	entries = new HiScoreEntry[entry_num];
	int nread = fread(entries, sizeof(HiScoreEntry), entry_num, file);
	return (0==nread?1:0);
}

void StandardHiScore::Save(char *f)
{
	if (entry_num == 0 || f[0] == 0) {
		printf("cannot save empty hiscore...\n");
		return;
	}
	char path[strlen(hi_dir) + strlen(f) + 1];
    sprintf(path, "%s%s", hi_dir, f);
	FILE *file = fopen(path, "w");
	if (file == 0) {
	    printf("cannot write '%s': permission denied...\n", f);
	    return;
	}
	Save(file);
	fclose(file);
}

void StandardHiScore::Save(FILE* file) 
{
	fwrite(&entry_num, sizeof(int), 1, file);
	fwrite(entries, sizeof(HiScoreEntry), entry_num, file);
}

void StandardHiScore::Save()
{
	Save(filename);
}

HiScoreEntry StandardHiScore::Entry(int i, int t/*=0*/)
{
	i = (i < 0) ? 0 : (i >= entry_num) ? entry_num - 1 : i;
	return entries[i];
}

int StandardHiScore::CheckEntry(HiScoreEntry *entry)
{
	for (int i = 0; i < entry_num; i++)
		if (entry->score > entries[i].score || (entry->score == entries[i].score && entry->level < entries[i].level)) {
			//found
			for (int j = entry_num - 1; j > i; j--)
				entries[j] = entries[j - 1];
			entries[i] = *entry;
			return i+1;
		}
		
	return 0;
}
