#pragma once

#include <maps/wikimap/mapspro/services/renderer/src/data_sets/include/source_layer.h>
#include <maps/renderer/libs/data_sets/data_set/include/view_queriable.h>
#include <maps/renderer/libs/feature/include/yandex/maps/renderer/feature/feature.h>

#include <pqxx/result>
#include <optional>

namespace maps::wiki::renderer {

using Transform = std::function<void(mr::base::PointD& vtx)>;

class MarkingGeometryIter;
class MarkingFeatureIter;

class PostgisFeatureIterable : public mr::data_set::FeatureIterable {
    friend class PostgisFeatureIter;
    friend class MarkingGeometryIter;
    friend class MarkingFeatureIter;
public:
    PostgisFeatureIterable(
        std::shared_ptr<pqxx::result> data,
        const SourceLayer& srcLayer,
        const Transform& transform,
        mr::base::Zoom zoom);

    std::unique_ptr<mr::feature::FeatureIter> iterator() const final;

private:
    using ColumnIndex = pqxx::row::size_type;

    std::shared_ptr<pqxx::result> data_;
    mr::feature::FeatureType ftType_;
    mr::base::Zoom layerMinZoom_;
    Transform transform_;
    std::optional<FeatureGeneratorType> featureGenerator_;
    mr::base::Zoom zoom_;

    ColumnIndex idIdx;
    ColumnIndex geomIdx;
    std::optional<ColumnIndex> minzoomIdx;
    std::optional<ColumnIndex> maxzoomIdx;
    std::optional<ColumnIndex> zlevBegIdx;
    std::optional<ColumnIndex> zlevEndIdx;
    std::vector<std::pair<std::string, ColumnIndex>> attrColumnIndexes;
};

class PostgisFeatureIter: public mr::feature::FeatureIter {
public:
    PostgisFeatureIter(const PostgisFeatureIterable* host);

    bool hasNext() const final;
    mr::feature::Feature& next() final;

private:
    void setAttributes(const pqxx::row& tuple);

private:
    const PostgisFeatureIterable* host_;
    size_t idx_;
    mr::feature::Feature feature_;
};

} // namespace maps::wiki::renderer
