#include "stdafx.h"
#include "StatsRecorder.h"
#include <fstream>

namespace MP
{
  StatsRecorder::~StatsRecorder()
  {
    stop();
    clearQueue();
    const Task::time_point gameLength = static_cast<Task::time_span>(Task::getCurrentTime()) - static_cast<Task::time_span>(m_beginTime);

    std::string path = "bwapi-data/logs/MPSchedulerStats";
#ifdef USE_MULTITHREADED_SCHEDULER
    path += "MP";
#else
    path += "SP";
#endif
    path += ".txt";

    WIN32_FILE_ATTRIBUTE_DATA attr;
    bool empty;
    if(GetFileAttributesExA(path.c_str(), GetFileExInfoStandard, &attr))
      empty = attr.nFileSizeHigh == 0 && attr.nFileSizeLow == 0;
    else
      empty = true;
    std::ofstream out(path.c_str(), std::ios_base::out | std::ios_base::app);
    if(empty)
      out << "Time\tThread count\tTotal run time\tTasks completed\tLongest wait time\tGame length" << std::endl;

    time_t rawtime; 
    time(&rawtime);
    struct tm timeinfo;
    localtime_s(&timeinfo, &rawtime);
    char buffer[80]; 
    strftime(buffer, sizeof(buffer), "%Y/%m/%d %H:%M:%S", &timeinfo);
    out << buffer << '\t' << m_threadCount << '\t' << (m_totalRunTime / 100LL) << '\t' << m_tasksCompleted << '\t' << (m_longestWaitTime / 100LL) << '\t' << (gameLength / 100LL) << std::endl;
  }
  void StatsRecorder::handle(const PendingTaskEvent &ev) const
  {
    if(ev.type == TaskEventTypes::Starting)
    {
      m_events.insert(std::make_pair(ev.event.id, ev.event));
    }
    else
    {
      const TaskEvent &end = ev.event;
      EventMap::iterator it = m_events.find(end.id);
      if(it != m_events.end())
      {
        const TaskEvent &start = it->second;
        const Task::time_span startTime = static_cast<Task::time_span>(start.createTime);
        const Task::time_span endTime = static_cast<Task::time_span>(end.time);
        m_totalRunTime += (endTime - static_cast<Task::time_span>(start.time));
        m_longestWaitTime = std::max(m_longestWaitTime, startTime - static_cast<Task::time_span>(end.createTime));
        ++m_tasksCompleted;
        m_events.erase(it);
      }
    }
  }
  void StatsRecorder::onTaskStarted(const TaskEvent &ev)
  {
    push(PendingTaskEvent(ev, TaskEventTypes::Starting));
  }
  void StatsRecorder::onTaskEnded(const TaskEvent &ev)
  {
    push(PendingTaskEvent(ev, TaskEventTypes::Ending));
  }
}