#include "./asyncjoy.h"
#include "./chunky.h"
#include "./str_utils.h"

AllocTracker trackAsyncJoy("AsyncJoy");

AsyncJoy::AsyncJoy(std::function<void(string const &err)> const &_cb)
  : cb(_cb),
    started(1),
    pending(1),
    triggered(0),
    errors(0)
{
  trackAsyncJoy.a();
}

AsyncJoy::~AsyncJoy()
{
  if (pending != 0) {
    L() << "AsyncJoy: destructed with " << pending << " pending threads\n";
  }
  trackAsyncJoy.f();
}


string AsyncJoy::progress()
{
  if (triggered) {
    return "done";
  }
  else {
    return repr(started - pending) + " / " + repr(started);
  }
}


void AsyncJoy::setError(string const &str)
{
  errors++;
  std::lock_guard lock(errorAccumMutex);
  if (!errorAccum.empty()) {
    errorAccum += "\n";
  }
  errorAccum += str;
}


void AsyncJoy::runCallbacks()
{
  if (triggered++) {
    throw logic_error("Callback already triggered"s);
  }
  if (errors) {
    std::unique_lock lock(errorAccumMutex);
    auto errorAccumCopy = errorAccum;
    lock.release();
    cb(errorAccumCopy);
  }
  else {
    cb(string());
  }
  cb = nullptr;
}
