#include "measurable_task.h"
#include "helpers.h"
#include "task_params.h"

#include <maps/libs/log8/include/log8.h>

namespace maps::wiki::exporter {

MeasurableTask::MeasurableTask(
        Functor fun,
        Logger& dbLogger,
        std::string label,
        LogTaskMode logMode)
    : fun_(std::move(fun))
    , dbLogger_(dbLogger)
    , label_(std::move(label))
    , duration_(std::chrono::milliseconds(0))
    , logMode_(logMode)
{}


void MeasurableTask::operator()()
{
    auto start = Clock::now();

    try {
        INFO() << label() << " started";
        if (logMode_ == LogTaskMode::OnStart || logMode_ == LogTaskMode::OnStartFinish) {
            dbLogger_.logInfo() << label() << " started";
        }

        fun_();

        duration_ = Clock::now() - start;

        INFO() << label() << " finished: " << FormattedDuration(duration_);
        if (logMode_ == LogTaskMode::OnFinish || logMode_ == LogTaskMode::OnStartFinish) {
            dbLogger_.logInfo() << label() << " finished: " << FormattedDuration(duration_);
        }
    } catch (const ExportCanceledException&) {
        duration_ = Clock::now() - start;
        throw;
    } catch (const std::exception& e) {
        duration_ = Clock::now() - start;
        throw ExportError() << label() << " failed: " << e.what();
    }
}


void runMeasurable(
    MeasurableTask::Functor fun,
    Logger& dbLogger,
    std::string label,
    LogTaskMode logMode)
{
    MeasurableTask mTask(fun, dbLogger, std::move(label), logMode);
    mTask();
}

} // namespace maps:::wiki::exporter
