#pragma once

#include <balancer/kernel/module/iface.h>
#include <balancer/kernel/ctl/ctl.h>

namespace NSrvKernel {

    struct TPolicyFeatures {
        bool WantsHash = false;
    };

    struct TStepParams {
        TStepParams(const TConnDescr* descr, size_t attempts, const TRequestHash* hash = nullptr)
            : Descr(descr)
            , Attempts(attempts)
            , Hash(hash)
        {
            if (!Hash && Descr) {
                Hash = &Descr->Hash;
            }
        }

        const TConnDescr* Descr;
        size_t Attempts;
        const TRequestHash* Hash;
    };

    class IBackend;
    class IAlgorithm;

    class IPolicy {
    public:
        virtual ~IPolicy() = default;

        virtual void MarkAsRetry() /* noexcept */ = 0;
        virtual IBackend* Next(IAlgorithm* algorithm, bool fastAttempt) /* noexcept */ = 0;
        virtual void RegisterSuccess() /* noexcept */ {}
        virtual void RegisterFail() /* noexcept */ {}
    };

    class IPolicyFactory {
    public:
        virtual ~IPolicyFactory() = default;

        virtual THolder<IPolicy> ConstructPolicy(const TStepParams& params) noexcept = 0;

        virtual void FillFeatures(TPolicyFeatures& features) const noexcept = 0;

        virtual void Init(IWorkerCtl* process) = 0;
    };
}  // namespace NSrvKernel
