// SPDX-License-Identifier: Unlicense

#include "stats.h"

#include "file.h"
#include "global.h"
#include "ini.h"
#include "string_.h"

static std::map<std::u8string, std::map<std::u8string, std::u8string>> serialize(SongIndex songIndex)
{
  const std::vector<Arrangement::Info>& arrangementInfos = Global::songInfos[songIndex].arrangementInfos;

  std::map<std::u8string, std::map<std::u8string, std::u8string>> serializedSaves;

  for (const auto& arrangementInfo : arrangementInfos)
  {
    std::map<std::u8string, std::u8string> serializedSave;

    if (Global::songStats.contains(arrangementInfo.persistentId))
    {
      const SongStats& songStats = Global::songStats.at(arrangementInfo.persistentId);

      if (songStats.timesPlayed > 0)
      {
        serializedSave.insert({ u8"TimesPlayed", to_string(songStats.timesPlayed)});
      }
      if (songStats.lastPlayed > 0)
      {
        serializedSave.insert({ u8"LastPlayed", to_string(songStats.lastPlayed) });
      }
      if (songStats.score > 0.0f)
      {
        serializedSave.insert({ u8"Score", to_string(songStats.score) });
      }
      if (songStats.sfxBankIndex >= 0)
      {
        serializedSave.insert({ u8"ToneBank", to_string(songStats.sfxBankIndex) });
      }
    }

    if (serializedSave.size() >= 1)
      serializedSaves.insert({ arrangementInfo.persistentId, serializedSave });
  }

  return serializedSaves;
}

static void loadSongStats(const std::pair<std::u8string, std::map<std::u8string, std::u8string>>& entry)
{
  SongStats& songStats = Global::songStats[entry.first];
  if (entry.second.contains(u8"LastPlayed"))
    songStats.lastPlayed = atoi(reinterpret_cast<const char*>(entry.second.at(u8"LastPlayed").c_str()));
  if (entry.second.contains(u8"Score"))
    songStats.score = f32(atof(reinterpret_cast<const char*>(entry.second.at(u8"Score").c_str())));
  if (entry.second.contains(u8"TimesPlayed"))
    songStats.timesPlayed = atoi(reinterpret_cast<const char*>(entry.second.at(u8"TimesPlayed").c_str()));
  if (entry.second.contains(u8"ToneBank"))
    songStats.sfxBankIndex = atoi(reinterpret_cast<const char*>(entry.second.at(u8"ToneBank").c_str()));
}

void Stats::init()
{
  if (!File::exists(Settings::pathStatsIni.c_str()))
    return;

  const std::vector<u8> statsIniData = File::read(Settings::pathStatsIni.c_str());
  const std::map<std::u8string, std::map<std::u8string, std::u8string>> serializedSaves = Ini::loadIniContent((const char8_t*)statsIniData.data(), statsIniData.size());

  for (const std::pair<std::u8string, std::map<std::u8string, std::u8string>>& pair : serializedSaves)
  {
    loadSongStats(pair);
  }
}

void Stats::fini()
{
  std::map<std::u8string, std::map<std::u8string, std::u8string>> serializedSaves;

  for (SongIndex songIndex = 0; songIndex < SongIndex(Global::songInfos.size()); ++songIndex)
  {
    const std::map<std::u8string, std::map<std::u8string, std::u8string>> map = serialize(songIndex);
    serializedSaves.insert(map.begin(), map.end());
  }

  Ini::saveIniFile(Settings::pathStatsIni.c_str(), serializedSaves);
}
