#include "memory_indexer_updater.h"
#include "memory_indexer.h"
#include "search_manager.h"

#include <saas/rtyserver/components/indexer/index_parsed_entity.h>
#include <saas/rtyserver/config/const.h>
#include <saas/util/logging/exception_process.h>

#include <kernel/groupattrs/docsattrs.h>

TMemoryIndexerUpdater::TMemoryIndexerUpdater(TMemoryIndexer& owner)
    : TIndexUpdater(owner)
    , MemoryIndexer(owner)
{}

bool TMemoryIndexerUpdater::UpdateDoc(ui32 docId, const TParsedDocument::TPtr doc) {
    return UpdateGroupAttributes(docId, *doc) | UpdateFillers(docId, *doc) | TIndexUpdater::UpdateDoc(docId, doc);
}

bool TMemoryIndexerUpdater::UpdateGroupAttributes(ui32 docId, const TParsedDocument& doc) {
    TGuard<TMutex> g(MemoryIndexer.MutexIndex);
    if (!MemoryIndexer.DocIds.HasDoc(docId)) {
        WARNING_LOG << "TMemoryIndexerUpdater::UpdateGroupAttributes: docId " << docId << " no longer exists" << Endl;
        return false;
    }
    const NGroupingAttrs::TDocsAttrs* mutableDocsAttrs = MemoryIndexer.SearchManager->GetDocsAttrs();
    if (!mutableDocsAttrs)
        return true;
    const NGroupingAttrs::TConfig& conf = mutableDocsAttrs->Config();
    const TIndexParsedEntity* indexDoc = doc.GetComponentEntity<TIndexParsedEntity>(MemoryIndexer.Config.Common.Owner.IndexGenerator);
    if (!indexDoc || indexDoc->GetGroupingAttributes().empty())
        return false;
    NRealTime::TIndexedDoc indexedDoc;
    for (NRTYServer::TAttrs::const_iterator i = indexDoc->GetGroupingAttributes().begin(); i != indexDoc->GetGroupingAttributes().end(); ++i) {
        TRY
            NRealTime::TIndexedDoc::TAttr* newAttr = indexedDoc.AddAttrs();
            ui32 attrnum = conf.AttrNum(i->first.data());
            TCateg value(0);
            if (attrnum != NGroupingAttrs::TConfig::NotFound) {
                newAttr->SetSizeOfInt((NRealTime::TIndexedDoc::TAttr::TAttrType)conf.AttrType(attrnum));
                mutableDocsAttrs->DocCateg(docId, attrnum, value);
            } else
                newAttr->SetSizeOfInt((NRealTime::TIndexedDoc::TAttr::TAttrType)conf.GetType(FromString<TCateg>(i->second.Values[0])));
            newAttr->SetName(i->first);
            newAttr->SetValue(ToString(NRTYServer::TAttr::GetUpdateValue<TCateg>(value, i->second.Values[0], i->second.Action)));
            newAttr->SetType(TFullDocAttrs::AttrGrInt);
        CATCH("Url = " +  doc.GetDocSearchInfo().GetUrl() + "attr = " + i->first)
    }
    const TMemoryIndexer::TRTYMemDocInfo& mdi = MemoryIndexer.DocIds.Get(docId);
    TDocSearchInfo docInfo(mdi.Url, mdi.Kps);
    indexedDoc.SetLogelType(NRealTime::TIndexedDoc::UpdateLogel);
    NRealTime::TIndexedDoc::TUpdateMetaInfo& upd = *indexedDoc.AddUpdateMetaInfos();
    upd.SetDataSelection(NRealTime::TIndexedDoc::TUpdateMetaInfo::GroupAttributes);
    upd.SetAction(NRealTime::TIndexedDoc::TUpdateMetaInfo::UpdateValues);
    return NMemorySearch::CDR_OK == MemoryIndexer.SearchManager->Consume(&indexedDoc, docInfo, MemoryIndexer.CVWaitMutex, MemoryIndexer.MutexIndex, MemoryIndexer.ConsumeMetrics);
}

bool TMemoryIndexerUpdater::UpdateFillers(ui32 docid, const TParsedDocument& doc) {
    TGuard<TMutex> g(MemoryIndexer.MutexIndex);
    if (!MemoryIndexer.DocIds.HasDoc(docid)) {
        WARNING_LOG << "DocId " << docid << " no longer exists in MemorySearch" << Endl;
        return false;
    }

    auto entity = doc.GetComponentEntity<TBaseGeneratorParsedEntity>(MemoryIndexer.Config.Common.Owner.IndexGenerator);
    if (!entity || !entity->GetIndexedDoc()) {
        return false;
    }

    const TMemoryIndexer::TRTYMemDocInfo& mdi = MemoryIndexer.DocIds.Get(docid);
    const TDocSearchInfo docInfo(mdi.Url, mdi.Kps);
    NRealTime::TIndexedDoc indexedDoc(*entity->GetIndexedDoc());
    indexedDoc.SetLogelType(NRealTime::TIndexedDoc::UpdateLogel);

    NRealTime::TIndexedDoc::TUpdateMetaInfo& update = *indexedDoc.AddUpdateMetaInfos();
    update.SetDataSelection(NRealTime::TIndexedDoc::TUpdateMetaInfo::Fillers);
    update.SetAction(NRealTime::TIndexedDoc::TUpdateMetaInfo::UpdateValues);

    return NMemorySearch::CDR_OK == MemoryIndexer.SearchManager->Consume(&indexedDoc, docInfo, MemoryIndexer.CVWaitMutex, MemoryIndexer.MutexIndex, MemoryIndexer.ConsumeMetrics);
}
