#pragma once

#include "check_context_impl.h"
#include "check_meta.h"
#include "task_messages.h"
#include "loader/data_source.h"

#include <yandex/maps/wiki/validator/area_of_interest.h>
#include <yandex/maps/wiki/validator/message.h>
#include <yandex/maps/wiki/threadutils/scheduler.h>
#include <yandex/maps/wiki/threadutils/threadpool.h>

#include <yandex/maps/wiki/configs/editor/fwd.h>

#include <exception>
#include <memory>
#include <thread>
#include <vector>

namespace maps::wiki::validator {

class TaskContext
{
public:
    TaskContext(
        const ValidatorConfig& validatorConfig,
        CheckCardinality checkCardinality,
        pgpool3::Pool& pgPool,
        DBID branchId,
        DBID commitId,
        AreaOfInterest aoi,
        const ObjectIdSet& objectIds,
        const std::vector<CheckMeta>& checks,
        size_t checkThreadsCount,
        CanceledChecker canceledChecker);

    ~TaskContext();

    DBID branchId() const { return dataSource_.dbGateway().branch().id(); }
    DBID commitId() const { return dataSource_.dbGateway().commitId(); }
    const AreaOfInterest& aoi() const { return dataSource_.aoi(); }
    std::vector<TCheckId> checkIds() const;

    void run();

    MessageBuffer popMessages();

private:
    void runMasterThread();
    void runCategoryLoad(TCategoryId category, LoaderType loaderType);

    class CategoryLoadTasks;

private:
    DataSource dataSource_;
    ThreadPool dbReadWorkers_;
    ThreadPool categoryLoadWorkers_;
    std::vector<CheckMeta> checks_;
    const size_t checkThreadsCount_;
    CanceledChecker canceledChecker_;

    TaskMessages taskMessages_;
    std::thread masterThread_;
    std::exception_ptr lastError_;
};

typedef std::unique_ptr<TaskContext> TaskContextPtr;

} // namespace maps::wiki::validator
