#pragma once

#include <maps/wikimap/mapspro/services/mrc/libs/common/include/types.h>

#include <maps/libs/sql_chemistry/include/gateway_access.h>

#include <mapreduce/yt/interface/client.h>

#include <opencv2/opencv.hpp>

#include <cstdint>
#include <optional>
#include <string>
#include <string_view>
#include <vector>

namespace maps::mrc::yt {

using Reader = NYT::TTableReader<NYT::TNode>;
using Writer = NYT::TTableWriter<NYT::TNode>;

using Mapper = NYT::IMapper<Reader, Writer>;
using Reducer = NYT::IReducer<Reader, Writer>;

using Bytes = common::Bytes;

enum class PoolType {
    AdHoc,  // pool for manual operations
    Processing,  // pool for running production batch-processing operations
};

/// If @param poolType is not defined then neither pool_trees nor pool will be
/// specified in scheduling options
void addCpuSchedulingOptions(NYT::TNode* specPtr, std::optional<PoolType> poolType = std::nullopt);
void addGpuSchedulingOptions(NYT::TNode* specPtr, std::optional<PoolType> poolType = std::nullopt);

/// If @param poolType is not defined then neither pool_trees nor pool will be
/// specified in operation options
NYT::TNode baseCpuOperationSpec(std::string_view title, std::optional<PoolType> poolType = std::nullopt);
NYT::TNode baseGpuOperationSpec(std::string_view title, std::optional<PoolType> poolType = std::nullopt);

NYT::TNode baseWorkerSpec(const std::optional<std::string>& portoLayerPath);

constexpr std::string_view DEFAULT_GPU_PORTO_LAYER = "//home/maps/core/mrc/porto_layers/xenial_nvidia-418_cuda-10.1.tar.xz";
constexpr std::string_view DEFAULT_GPU_CUDA11_PORTO_LAYER = "//home/maps/core/mrc/porto_layers/bionic_nvidia-465.19.01-0_cuda-11.3.1-1.tar.xz";

inline NYT::TNode baseGpuWorkerSpec() { return baseWorkerSpec(std::string(DEFAULT_GPU_PORTO_LAYER)); }

template<typename T>
class FeatureWithImage {

public:
    FeatureWithImage(const T& feature, const cv::Mat& image)
        : feature(feature)
        , image(image)
    {}

    T feature;
    cv::Mat image;

private:
    // using Self = FeatureWithImage<T>;
    friend class sql_chemistry::GatewayAccess<FeatureWithImage>;

    FeatureWithImage()
        : feature(sql_chemistry::GatewayAccess<T>::construct())
    {}
};

} // namespace maps::mrc::yt
