#pragma once

#include <saas/api/indexing_client/multithread_client.h>
#include <saas/api/mr_client/processors/processors.h>

#include <mapreduce/yt/interface/client.h>
#include <mapreduce/yt/interface/node.h>
#include <mapreduce/yt/interface/io-inl.h>
#include <mapreduce/interface/all.h>

namespace NSaas {

    struct TSaasIndexerOption: public TMultithreadIndexerOption {
        TString Processor = "simple";
        TRowProcessorOptions ProcessorOptions;

        TSaasIndexerOption() {}

        TSaasIndexerOption(const TString& host, ui16 port, const TString& key)
            : TMultithreadIndexerOption(host, port, key)
        {}

        int operator& (IBinSaver& f) {
            TMultithreadIndexerOption::operator& (f);
            f.AddMulti(Processor, ProcessorOptions);
            return 0;
        }

        inline void Save(IOutputStream* s) const {
            TMultithreadIndexerOption::Save(s);
            ::SaveMany(s, Processor, ProcessorOptions);
        }

        inline void Load(IInputStream* s) {
            TMultithreadIndexerOption::Load(s);
            ::LoadMany(s, Processor, ProcessorOptions);
        }
    };

    class TSaasIndexerMap : public NMR::IMap {
        OBJECT_METHODS(TSaasIndexerMap)
    private:
        TSaasIndexerMap() {}
    public:
        TSaasIndexerMap(const TSaasIndexerOption& options)
            : Options(options)
        {}

        virtual void Start(ui32 jobId, ui64 recordStart, NMR::TUpdate& output) override;
        virtual void Finish(ui32 jobId, NMR::TUpdate& output) override;
        virtual void DoSub(NMR::TValue key, NMR::TValue subkey, NMR::TValue value, NMR::TUpdate &output) override;

    private:
        TSaasIndexerOption Options;
        THolder<TMultithreadIndexer> Indexer;
        THolder<IRowProcessor> RowProcessor;
        mutable TMutex UpdateMutex;

        SAVELOAD_OVERRIDE_WITHOUT_BASE(Options)
    };

    class TSaasYTMapper : public NYT::IMapper<NYT::TTableReader<NYT::TNode>, NYT::TTableWriter<NYT::TNode>> {
        using TBase = NYT::IMapper<NYT::TTableReader<NYT::TNode>, NYT::TTableWriter<NYT::TNode>>;
    public:
        using TReader = TBase::TReader;
        using TWriter = TBase::TWriter;

    public:
        TSaasYTMapper() = default;
        TSaasYTMapper(const TSaasIndexerOption& options)
            : Options(options)
        {}

        Y_SAVELOAD_JOB(Options);

        virtual void Start(TWriter* writer) override;
        virtual void Finish(TWriter* writer) override;
        void Do(TBase::TReader* input, TBase::TWriter* output) override;

    private:
        TSaasIndexerOption Options;
        THolder<TMultithreadIndexer> Indexer;
        THolder<IRowProcessor> RowProcessor;
    };
}
