#pragma once

#include "params.h"
#include "revision_meta/common.h"

#include <yandex/maps/wiki/common/extended_xml_doc.h>
#include <yandex/maps/wiki/common/pgpool3_helpers.h>
#undef D
#undef W

#include <condition_variable>
#include <mutex>

namespace maps {
namespace wiki {
namespace contours {

const std::string DB_CORE = "core";
const std::string DB_LONG_READ = "long-read";
const std::string DB_VIEW_TRUNK = "view-trunk";
const std::string POOL_CORE = "core";
const std::string POOL_EDITOR_TOOL = "editor-tool";

/**
 * Copy contour objects from \p revisionPool to \p viewPool.
 * \return true if there was any commit to handle since last call.
 * For first time it copies all contour objects.
 */
bool handleNextCommits
    ( common::PoolHolder& revisionPool
    , common::PoolHolder& viewPool
    , const Params& params
    );

void handleIdsFromFile
    ( common::PoolHolder& revisionPool
    , common::PoolHolder& viewPool
    , const Params& params
    );

/**
 * \brief delete watermark to allow a service to resync view
 */
void resetWatermark(common::PoolHolder& viewPool, const Params& params);

inline
std::shared_ptr<common::PoolHolder> makePoolHolder
    ( const common::ExtendedXmlDoc& doc
    , const std::string& db
    , const std::string& pool
    ) try
{
    return std::make_shared<common::PoolHolder>(doc, db, pool);
} catch (const xml3::NodeNotFound&) {
    return std::make_shared<common::PoolHolder>(doc, DB_CORE, POOL_CORE);
}

/**
 * \brief SIG_TERM catcher and alarm clock
 */
class SignalListener {
public:
    ~SignalListener() { detach(); }
    static SignalListener& singleton();
    bool isStopped(); // SIG_TERM

    template <typename Duration>
    void sleep(Duration&& waitInterval) // for defined interval or SIG_TERM
    {
        std::unique_lock<std::mutex> lck(mtx_);
        condVar_.wait_for(lck, waitInterval, [this]{ return isStopped_; });
    }

private:
    std::mutex mtx_;
    std::condition_variable condVar_;
    bool isStopped_;

    SignalListener();
    void detach();
    void stop();
    static void signalHandler(int sig);
};

/**
 * \brief delete contour objects with ID not in list
 *        (in h-file for unit-test only)
 */
void removeDifference
    ( common::PoolHolder& viewPool
    , const revision_meta::TObjectIdSet& ids
    );

} // contours
} // wiki
} // maps
