#pragma once

#include <util/generic/vector.h>
#include <util/generic/ptr.h>
#include <util/string/split.h>
#include <saas/api/action.h>

#include <search/session/compression/compression.h>

#include <mapreduce/interface/all.h>
#include <mapreduce/yt/interface/node.h>

#include <library/cpp/object_factory/object_factory.h>

namespace NSaas {

    struct TRowProcessorOptions {
        NMetaProtocol::ECompressionMethod Compression = NMetaProtocol::CM_COMPRESSION_NONE;
        ui64 Timestamp = Max<ui64>();
        ui64 Prefix = 0;
        ui32 DeadlineMinutesUTC = 0;
        TAction::TActionType ActionType = TAction::atModify;
        TString OtherOptions = TString();
        THashMap<TString, TString> ExtraOptions;

        SAVELOAD(Compression, Timestamp, Prefix, DeadlineMinutesUTC, ActionType, OtherOptions, ExtraOptions)
        Y_SAVELOAD_DEFINE(Compression, Timestamp, Prefix, DeadlineMinutesUTC, ActionType, OtherOptions, ExtraOptions)
    };

    class TRowProcessorDecorator;

    class IRowProcessor {
    public:
        using TFactory = NObjectFactory::TParametrizedObjectFactory<IRowProcessor, TString, TRowProcessorOptions>;
        friend class TRowProcessorDecorator;
    public:
        IRowProcessor(const TRowProcessorOptions& options);
        virtual ~IRowProcessor() = default;

        TVector<TAction> ProcessRow(const NYT::TNode& row);
        TVector<TAction> ProcessRow(const NMR::TValue& key, const NMR::TValue& subkey, const NMR::TValue& value);

        TAction ProcessRowSingle(const NYT::TNode& row); // DEPRECATED
        TAction ProcessRowSingle(const NMR::TValue& key, const NMR::TValue& subkey, const NMR::TValue& value); // DEPRECATED

        virtual bool ShouldSkipRow(const NYT::TNode& row) const;
        virtual bool NeedConfigFiles() const;

    protected:
        virtual void DoValidateRow(const NYT::TNode& row) = 0;
        virtual TVector<TAction> DoProcessRow(const NYT::TNode& row);
        virtual TAction DoProcessRowSingle(const NYT::TNode& row); // DEPRECATED

    protected:
        TRowProcessorOptions Options;
    };

    class IDataRowProcessor : public IRowProcessor {
        using IRowProcessor::IRowProcessor;

    protected:
        TAction DoProcessRowSingle(const NYT::TNode& row) override;
        virtual void DoFillKps(TAction& action, const NYT::TNode& row) = 0;
        virtual void DoFillUrl(TDocument& doc, const NYT::TNode& row) = 0;
        virtual void DoFillBody(TDocument& doc, const NYT::TNode& row) = 0;

        void AddProperty(NSaas::TDocument& doc, const TString& key, const TString& value);
        void AddProperty(NSaas::TDocument& doc, const TString& keyEqualsValue);
        void AddTag(NSaas::TDocument& doc, const TString& key, const TString& value);

    private:
        TAction CreateDefaultAction();
    };

    class TRowDecoratorFactory {
    public:
        static IRowProcessor* Construct(const TString& key, const TRowProcessorOptions& options);
    };
} // namespace NSaas
