#pragma once

#include <yandex/maps/wiki/diffalert/storage/stored_message.h>
#include <yandex/maps/wiki/common/geom.h>
#include <yandex/maps/wiki/threadutils/threadedqueue.hpp>
#include <maps/libs/pgpool/include/pgpool3.h>

#include <atomic>
#include <cstdint>
#include <future>
#include <list>
#include <memory>
#include <vector>

namespace maps {
namespace wiki {
namespace diffalert {

class StoredMessage;

struct DiffalertRegion
{
    common::Geom geometry;
    RegionPriority priority;
};

inline bool operator<(const DiffalertRegion& lhs, const DiffalertRegion& rhs)
{
    return lhs.priority < rhs.priority;
}

class ResultsWriter
{
public:
    ResultsWriter(TaskId taskId, pgpool3::Pool& connPool);

    ResultsWriter(
        TaskId taskId,
        pgpool3::Pool& connPool,
        std::vector<DiffalertRegion> sortedRegions);

    ~ResultsWriter();

    TaskId taskId() const { return taskId_; };

    void put(std::list<StoredMessage> messages);
    void finish();

    bool failed() const { return failed_; }

private:
    void stop() noexcept;

    void writerLoop();
    void writeBatch(const std::list<StoredMessage>& batch);
    void writeBatchWithRetries(const std::list<StoredMessage>& batch);

    RegionPriority findRegionPriority(const Envelope&) const;

    TaskId taskId_;
    pgpool3::Pool& connPool_;
    std::vector<DiffalertRegion> sortedRegions_;
    ThreadedQueue<StoredMessage> messagesQueue_;
    std::atomic<bool> failed_;
    std::future<void> writer_;
};

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