#include "hiscore.h"
#include "mystr.h"
#include "globals.h"

#include <iostream>
#include <fstream>

using namespace std;


HiscoreTable hiscore_table;

void HiscoreTable::Reset() {
  times.clear();
  scores.clear();
}

bool HiscoreTable::AddTime(std::string nm, HSTime v) {
  std::deque<HSTime> *list;
  list=(std::deque<HSTime> *) times.get(nm);
  if (list == NULL) {
    list = new std::deque<HSTime>;
    times.push_back(nm, list);
  }

  bool added;
  added=false;
  for (std::deque<HSTime>::iterator it=list->begin(); it!=list->end(); it+=1) {
    if (v.v < (*it).v) {
      list->insert(it, v);
      added=true;
      break;
    }
    else if ((v.v == (*it).v) && (v.name==(*it).name)) {
      return false;
    }
  }

  if (!added) {
    if (list->size() >= 10) return false;
    else list->push_back(v);
  }
  else {
    while (list->size() > 10) {
      list->pop_front();
    }
  }
  return true;
}

bool HiscoreTable::AddScore(std::string nm, HSScore v) {
  std::deque<HSScore> *list;
  list=(std::deque<HSScore> *) scores.get(nm);
  if (list == NULL) {
    list = new std::deque<HSScore>;
    scores.push_back(nm, list);
  }

  bool added;
  added=false;
  for (std::deque<HSScore>::iterator it=list->begin(); it!=list->end(); it+=1) {
    if (v.v > (*it).v) {
      list->insert(it, v);
      added=true;
      break;
    }
    else if ((v.v == (*it).v) && (v.name==(*it).name)) {
      return false;
    }
  }
  if (!added) {
    if (list->size() >= 10) return false;
    else list->push_back(v);
  }
  else {
    while (list->size() > 10) {
      list->pop_front();
    }
  }
  return true;
}


void HiscoreTable::Print() {
}



float HiscoreTable::GetBestTime(std::string nm) {
  std::deque<HSTime> *list;
  list=(std::deque<HSTime> *) times.get(nm);
  if (list != NULL) {
    return list->at(0).v;
  }
}

float HiscoreTable::GetBestScore(std::string nm) {
  std::deque<HSScore> *list;
  list=(std::deque<HSScore> *) scores.get(nm);
  if (list != NULL) {
    return list->at(0).v;
  }
}


void HiscoreTable::Save() {
  ofstream myfile;
  myfile.open ("Scores.dat", ios::out | ios::binary);

  int sz;
  sz = times.size();
  myfile.write(reinterpret_cast<char *>(&sz),sizeof(int));
  sz = scores.size();
  myfile.write(reinterpret_cast<char *>(&sz),sizeof(int));

  for (int i=0; i!=times.size();i+=1) {
    char map_name[64];
    strcpy(map_name, times.get_data(i)->GetIdentifier().c_str());
    myfile.write(reinterpret_cast<char *>(map_name),sizeof(char)*64);

    std::deque<HSTime> *l_1;
    l_1 = (std::deque<HSTime> *) times.get(ToString(map_name));
    sz = l_1->size();
    myfile.write(reinterpret_cast<char *>(&sz),sizeof(int));
    for (int i2=0; i2!=sz;i2+=1) {
      char sc_name[64];
      strcpy(sc_name, l_1->at(i2).name.c_str());
      myfile.write(reinterpret_cast<char *>(sc_name),sizeof(char)*64);
      myfile.write(reinterpret_cast<char *>(&(l_1->at(i2).v)),sizeof(float));
    }

    std::deque<HSScore> *l_2;
    l_2 = (std::deque<HSScore> *) scores.get(ToString(map_name));
    sz = l_2->size();
    myfile.write(reinterpret_cast<char *>(&sz),sizeof(int));
    for (int i2=0; i2!=sz;i2+=1) {
      char sc_name[64];
      strcpy(sc_name, l_2->at(i2).name.c_str());
      myfile.write(reinterpret_cast<char *>(sc_name),sizeof(char)*64);
      myfile.write(reinterpret_cast<char *>(&(l_2->at(i2).v)),sizeof(int));
    }

  }

  myfile.close();
}



void HiscoreTable::Load() {
  ifstream myfile;
  myfile.open ("Scores.dat", ios::in | ios::binary);

  int sz1, sz2, sz3, sz4;
  myfile.read(reinterpret_cast<char *>(&sz1),sizeof(int));
  myfile.read(reinterpret_cast<char *>(&sz2),sizeof(int));

  for (int i=0; i!=sz1;i+=1) {
    char map_name[64];
    myfile.read(reinterpret_cast<char *>(map_name),sizeof(char)*64);

    myfile.read(reinterpret_cast<char *>(&sz3),sizeof(int));
    for (int i2=0; i2!=sz3;i2+=1) {
      char sc_name[64];
      myfile.read(reinterpret_cast<char *>(sc_name),sizeof(char)*64);
      float v;
      myfile.read(reinterpret_cast<char *>(&v),sizeof(float));
      AddTime(ToString(map_name), HSTime(ToString(sc_name), v));
    }

    myfile.read(reinterpret_cast<char *>(&sz4),sizeof(int));
    for (int i2=0; i2!=sz4;i2+=1) {
      char sc_name[64];
      myfile.read(reinterpret_cast<char *>(sc_name),sizeof(char)*64);
      int v;
      myfile.read(reinterpret_cast<char *>(&v),sizeof(int));
      AddScore(ToString(map_name), HSScore(ToString(sc_name), v));
    }
  }

  myfile.close();
}
