#pragma once
#include "diff_context_impl.h"
#include "db_access.h"

#include <yandex/maps/wiki/common/exception_trap.hpp>
#include <yandex/maps/wiki/revision/revisionid.h>
#include <yandex/maps/wiki/threadutils/threadpool.h>
#include <yandex/maps/wiki/threadutils/threadedqueue.hpp>

#include <map>
#include <memory>
#include <vector>

namespace maps {
namespace wiki {
namespace revision {
namespace filters {

class ProxyFilterExpr;

} // namespace filters
} // namespace revision
namespace diffalert {

struct IdsBatch;
class EditorConfig;

class LongtaskObjectDiffsLoader
{
public:
    LongtaskObjectDiffsLoader(
        RevSnapshotFactory oldRevSnapshotFct,
        RevSnapshotFactory newRevSnapshotFct,
        const EditorConfig& config,
        size_t numThreads);

    void loadChangedObjects(
        const revision::RevisionIds& sortedOldRevIds,
        const revision::RevisionIds& sortedNewRevIds);
    void loadUnchangedObjects(const std::vector<TId>& oids);

    struct LoadLongtaskObjectDiffResult
    {
        std::list<LongtaskObjectDiff> objDiffs;
        std::list<TId> badObjects;
    };

    // Blocks until all diffs are loaded
    LoadLongtaskObjectDiffResult getAll();

private:
    void doLoadChangedObjects(const IdsBatch& idsBatch);
    void doLoadUnchangedObjects(const std::vector<revision::DBID>& batchOids);

    RevSnapshotFactory oldRevSnapshotFct_;
    RevSnapshotFactory newRevSnapshotFct_;
    const EditorConfig& config_;
    common::ExceptionTrap exceptionTrap_;
    ThreadPool threadPool_;
    ThreadedQueue<LongtaskObjectDiff> objDiffQueue_;
    ThreadedQueue<TId> badObjectQueue_;
};

revision::RevisionIds loadSortedRevisionIds(
    RevSnapshotFactory& revSnapshotFct,
    const revision::filters::ProxyFilterExpr& filter);

struct LoadLongtaskRelationDiffResult
{
    std::map<TId, LongtaskRelationsDiff> relDiffsByOid;
    std::list<TId> badRelations;
};

LoadLongtaskRelationDiffResult loadLongtaskRelationDiffs(
    const revision::RevisionIds& sortedOldRevIds,
    const revision::RevisionIds& sortedNewRevIds,
    RevSnapshotFactory& oldRevSnapshotFct,
    RevSnapshotFactory& newRevSnapshotFct,
    size_t numThreads);

} // namespace diffalert
} // namespace wiki
} // namespace maps
