#pragma once

#include <saas/rtyserver/factors/factors_plugin.h>
#include <saas/rtyserver/factors/factor.h>
#include <util/generic/array_ref.h>
#include <util/generic/ptr.h>

struct TRTYDynamicFeatureContext;
class TFactorStorage;

namespace NRTYFactors {
    class TConfig;
}

namespace NRTYFeatures {
    using TDynFactorInfo = NRTYFactors::TSimpleFactorDescription;

    using TDynFactorsIds = TArrayRef<const i32>;
    using TDynMappingItem = NRTYFactors::TDpFactorData;
    using TDynMapping = TVector<TDynMappingItem>;
    using TDynMappingRef = TArrayRef<const TDynMappingItem>;

    //
    // A class that calculates one or more dynamic factors. Created by IFeature.
    //
    class IFeatureCalcer: public TThrRefBase {
    public:
        using TPtr = TIntrusivePtr<IFeatureCalcer>;

    public:
        virtual void Calc(TFactorStorage& storage, const TRTYDynamicFeatureContext& ctx, ui32 docId) = 0;
    };

    //
    // Pluggable module that provides Dp (dynamic pluggable) factors. Injected to TRTYFeatures.
    //
    class IFeature: public TThrRefBase {
    public:
        using TPtr = TIntrusivePtr<IFeature>;
        using TAddFactorFunc = std::function<void(TDynFactorInfo)>;

    public:
        /// returns 0 if not applicable
        /// NB: factorsInRequest != factorsInConfig
        virtual IFeatureCalcer::TPtr CreateCalcer(const TDynMapping& factorsInRequest, const NRTYFactors::TConfig* relevCfg, bool fastFeaturesOnly) = 0;

        /// does nothing if not applicable
        virtual void InitModels(const TDynMapping& factorsInConfig, const NRTYFactors::TConfig* relevCfg, const TString& modelsPath) = 0;

        virtual void InitStaticInfo(TStringBuf modelsPath, TAddFactorFunc addFactor) = 0;
    };

    //
    // A special type of extension that uses TFactorStorage with slices.
    // Its usage is limited to text machines, so there are no generic routines, and no dependency injection as for now.
    //
    class ISlicedCalcer : public TThrRefBase {
    public:
        using TPtr = TIntrusivePtr<ISlicedCalcer>;

    public:
        virtual ~ISlicedCalcer() = default;
        // @detail Called before the batch. Should init the views
        virtual void Bind(TFactorStorage& storage) = 0;
        // @detail docId are guaranteed to be increasing between CalcFeatures calls
        virtual void CalcFeatures(ui32 docId) = 0;
    };
} // namespace NRTYFeatures
