#pragma once

#include "qs_component.h"

#include <saas/rtyserver/factors/factors_mask.h>
#include <saas/rtyserver/key_inv_processor/ki_maker.h>
#include <saas/rtyserver/components/erf/erf_disk.h>
#include <saas/rtyserver/components/qs/functions/qs_function_abstract.h>
#include <saas/rtyserver/indexer_core/abstract_model.h>

#include <ysite/yandex/posfilter/hits_loader.h>
#include <ysite/yandex/posfilter/tr_iterator.h>
#include <ysite/yandex/srchmngr/yrequester.h>
#include <ysite/yandex/posfilter/filtration_model.h>

#include <kernel/web_factors_info/factor_names.h>

#include <util/generic/string.h>

class TQSIterator {
private:
    TRichTreePtr Request;
    THolder<THitsLoader> HitsLoader;
    NRTYFactors::TQSFactorsList::TPtr QSFunction;
    THolder<TTopAndArgs> TopAndArgs;
    TRTYKIReader::TPtr KIReader;
    TRTYErfDiskManagerPtr ErfReader;

public:
    typedef TAtomicSharedPtr<TQSIterator> TPtr;
    typedef TAtomicSharedPtr<IQSFunction> TFunctionPtr;
    typedef THashMap<TString, TFunctionPtr> TFunctionsByName;

public:
    TQSIterator(TRTYKIReader::TPtr kiReader, TRTYErfDiskManagerPtr erfReader, const IQSRequest* cgi, NRTYFactors::TQSFactorsList::TPtr qsFunction, const TFunctionsByName& functionsByName);

    const NRTYFactors::TFactorsList& GetFactorsList() const {
        return QSFunction->GetFactorsList();
    }

    TTopAndArgs* GetTopAndArgs() {
        return TopAndArgs.Get();
    }

    const IRTYErfManager* GetErfManager() const {
        return ErfReader.Get();
    }
};

class TQSIteratorsPull {
private:
    TVector<TQSIterator::TPtr> Iterators;
    int DocId;
public:

    typedef TSimpleSharedPtr<TQSIteratorsPull> TPtr;

    TQSIteratorsPull()
    {
        DocId = -1;
    }

    void Add(TQSIterator* iterator) {
        TQSIterator::TPtr result = iterator;
        if (result->GetTopAndArgs())
            Iterators.push_back(result);
    }

    void ReadFactors(TFactorView& data, const ui32 docId);
    void CalcFactors(const TCalcFactorsContext& ctx) {
        TFactorView factors(static_cast<TBasicFactorStorage&>(*ctx.Factors));
        ReadFactors(factors, ctx.DocId);
    }
};

class TQSManager: public NRTYServer::IIndexComponentManager {
private:
    const TRTYServerConfig& Config;
    const NRTYFactors::TQSFactorsHashList& FactorsList;
    TPathName Dir;
    TVector<NRTYFactors::TQSFactorsList::TPtr> FactorsInfo;
    TVector<TRTYKIReader::TPtr> Readers;
    TVector<TRTYErfDiskManagerPtr> Erfs;
    TQSIterator::TFunctionsByName FunctionsByName;
public:
    TQSManager(const NRTYServer::TManagerConstructionContext& context);
    bool DoOpen() override;
    bool DoClose() override;
    ui32 GetDocumentsCount() const override;
    void InitInteractions(const NRTYServer::IIndexManagersStorage& /* storage */) override;
    bool GetDocInfo(const ui32 docId, NJson::TJsonValue& result) const override;
    TQSIteratorsPull::TPtr BuildIteratorsPull(const IQSRequest* cgi, const NRTYFactors::TRTYFactorMask* rtyFactorMask) const;
};
