#pragma once

#include "yt_command.h"
#include "config_files.h"

#include <saas/api/mr_client/processors/processors.h>
#include <saas/library/index_snapshot/snapshot_manager.h>
#include <saas/library/daemon_base/config/options.h>
#include <saas/library/yt/stream/yt_chunked_output.h>
#include <saas/library/yt/common/yt_blob.h>

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

#include <library/cpp/getopt/last_getopt.h>

#include <util/datetime/base.h>
#include <util/folder/path.h>
#include <util/generic/map.h>
#include <util/generic/vector.h>
#include <util/system/execpath.h>

enum class ECookFormat {
    Full   /* "full" */,
    Delta  /* "delta" */
};

class TYTIndexer {
public:
    struct TOptions {
        TString CommandLine;

        TDaemonOptions DaemonOptions;
        TRtyConfigBundle IndexingConfigBundle;
        TRtyConfigBundle MergingConfigBundle;

        TString SearchMapText;

        TString Proxy;
        TVector<TString> Src;
        TString DstDir;
        TString Dst;
        TString ResourceDst;
        TString IncorrectDocsDst;
        TString TmpDir;
        TString ServiceName;
        TString SearchMapPath;
        TString Processor = "personal";
        TString ReportFilePath;
        ECookFormat CookFormat = ECookFormat::Full;
        EYTBlobFormat BlobFormat = EYTBlobFormat::Old;
        ui32 DumperChunkSize = TYTChunkedOutput::DefaultChunkSize;
        NSaas::TRowProcessorOptions ProcessorOptions;
        TString SnapshotManager = "yt";
        IIndexSnapshotManager::TContext SnapshotManagerContext;
        ui64 MaxDocumentsPerSegment = 0;
        ui32 MinSegmentsCount = 0;

        ui32 IndexerRamGb = 30;
        ui32 IndexerTmpfsGb = 30;
        float IndexerRamReserveFactor = 0.5;
        ui32 IndexerCpu = 1;

        bool AddExtraTimestamp = false;

        ui32 IndexerRamMapperGb = 0;
        ui32 MaxRowWeightMb = 0;

        bool CutConfigIncludes = true;
        TYTConfigFiles ConfigFiles;
        TString DictPath = TFsPath(GetExecPath()).Parent() / "dict.dict";
        TVector<TString> AttachPath;

        bool Publish = false;
        bool SplitSegments = false;
        bool Resume = false;
        bool Verbose = false;
        bool DryRun = false;
        bool KeepTemps = false;
        bool Force = false;
        bool SkipIndexing = false;
        bool ForbidSameUrls = false;
        bool SaveDeletedDocuments = false;
        bool EnableSkyShare = false;

        ui32 SampleUrlsNum = 100;
        bool SampleShards = false;

        bool FailOnIndexError = false;
        bool FilterIncorrectDocs = false;

        // Enable DATALESS optimization in merging reducer, the mode is broken: https://st.yandex-team.ru/SAAS-5603
        bool UseDatalessPartsOnMerge = false;

        TString IndexerModulesToRun; // comma-separated list of daemon modules to run inside indexer jobs
        TString MergerModulesToRun; // comma-separated list of daemon modules to run inside merger jobs

        NYT::TNode Acl;

    public:
        TOptions(int argc, const char* argv[]);
        void BindToOpts(NLastGetopt::TOpts& opts);
        void PostProcess(TVector<TString> freeArgs);
    };

public:
    TYTIndexer(int argc, const char* argv[]);
    void Run();

private:
    void InitNeedToIndex();
    void InitTmpTables();
    void InitCommands();
    void DeleteTmpTables();
    void SaveSampleTable();
    void PrintVerbose(const TString& msg);

private:
    const TOptions Options;

    bool NeedToIndex;
    NYT::IClientPtr ClientPtr;
    TVector<NYT::TRichYPath> SrcDocs;
    NYT::TRichYPath DstIndex;
    TMap<TString, NYT::TRichYPath> TmpTables;
    TVector<THolder<TYTCommand>> Commands;
    NSaas::TYTLaunchReport Report;
};
