#pragma once

#include "qs_const.h"
#include <saas/rtyserver/indexer_core/parsed_document.h>
#include <saas/rtyserver/key_inv_processor/ki_actor.h>
#include <saas/rtyserver/indexer_core/document_parser.h>
#include <saas/rtyserver/factors/factors_abstract.h>
#include <saas/rtyserver/factors/factors_blocks.h>
#include <saas/rtyserver/factors/factor.h>

class TDocumentQSInfo {
public:
    class TFactorStorageSafe : public TFactorStorage {
    public:
        TFactorStorageSafe() : TFactorStorage() {}
    };

    typedef TMap<TString, TFactorStorageSafe> TFactorsByKey;
private:
    TFactorsByKey Data;
    TVector<ui32> Remap;
    NRTYFactors::TQSFactorsList::TPtr FactorsInfo;
public:

    void Serialize(NRTYServer::TMessage::TQSInfo& qsInfo) const {
        for (ui32 i = 0; i < FactorsInfo->GetFactorsList().size(); ++i) {
            qsInfo.AddFactorNames(FactorsInfo->GetFactorsList()[i].Name);
        }

        for (TFactorsByKey::const_iterator i = Data.begin(), e = Data.end(); i != e; ++i) {
            NRTYServer::TMessage::TFactorsByKey* factors = qsInfo.AddFactors();
            factors->SetKey(i->first.substr(QSFactorKeyPrefix.size()));
            for (ui32 f = 0; f < i->second.Size(); ++f) {
                factors->MutableValues()->AddValues()->SetValue(i->second[f]);
            }
        }

    }

    const TFactorsByKey& GetData() const {
        return Data;
    }

    void SetFactorsInfo(NRTYFactors::TQSFactorsList::TPtr factorsInfo) {
        FactorsInfo = factorsInfo;
    }

    void AddRemapInfo(ui32 index) {
        Remap.push_back(index);
    }

    void AddInfo(const NRTYServer::TMessage::TFactorsByKey& info);
    void ApplyPatch(const TDocumentQSInfo& patch);
};

class TQSParsedEntity : public TParsedDocument::TParsedEntity {
public:
    TQSParsedEntity(TConstructParams& params);

    const THashMap<TString, TDocumentQSInfo>& GetDocInfos() const {
        return FactorsByQS;
    }

    const TDocumentQSInfo& GetDocInfo(const TString& qsName) const {
        THashMap<TString, TDocumentQSInfo>::const_iterator i = FactorsByQS.find(qsName);
        VERIFY_WITH_LOG(i != FactorsByQS.end(), "incorrect TQSParsedEntity::GetDocInfo usage");
        return i->second;
    }

    virtual void MergeToProto(NRTYServer::TParsedDoc& pd, const NRTYServer::TDocSerializeContext& context) const;
    void AddQSInfo(const NRTYServer::TMessage::TQSInfo& qsInfo, const NRTYFactors::TQSFactorsList::TPtr factorsInfo, bool needInCheckFullFactorsList);
protected:
    virtual void DoApplyPatch(const TParsedDocument& doc);
private:
    THashMap<TString, TDocumentQSInfo> FactorsByQS;
};

class TQSStaticFactors: public IRTYStaticFactors {
private:
    const NRTYFactors::TFactorsList FactorsList;
public:

    explicit TQSStaticFactors(const NRTYFactors::TFactorsList factorsList)
        : FactorsList(factorsList)
    {

    };

    virtual ui32 GetStaticFactorsCount() const override {
        return FactorsList.size();
    }

    virtual const NRTYFactors::TSimpleFactorDescription& GetFactor(ui32 index) const override {
        VERIFY_WITH_LOG(FactorsList.size() > index, "%lu > %u", FactorsList.size(), index);
        return FactorsList[index];
    }
};


class TQSComponentParser: public TComponentParser {
public:
    virtual void Parse(TParsingContext& context) const;
};
