#pragma once

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

namespace NSrvKernel {

class IBackend;

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

    virtual bool Has() const noexcept = 0;
    virtual TRequestHash Get() noexcept = 0;
    virtual void Set(TRequestHash hash) noexcept = 0;
};


class IAlgorithm { // TODO: rename to balancing algorithm or algorithm iteration
public:
    explicit IAlgorithm(IWorkerCtl* process) : Process_(process) {}
    virtual ~IAlgorithm() = default;

    virtual void RemoveSelected(IBackend*) /* noexcept */ = 0;
    virtual void Reset() /* noexcept */ = 0;

    virtual IBackend* Next() /* noexcept */ = 0;

    virtual void Select(IBackend*) /* noexcept */ {}

    virtual IBackend* SelectNext() /* noexcept */ {
        IBackend* result = Next();
        if (result) {
            Select(result);
        }
        return result;
    }

    virtual IBackend* NextByName(TStringBuf, bool /*allowZeroWeights*/) /* noexcept */ {
        return nullptr;
    }

    virtual IBackend* NextByHash(IHashProcessor&) /* noexcept */ {
        return nullptr;
    }

    IWorkerCtl* Process_ = nullptr;
};

class TFakeAlgorithm : public IAlgorithm {
public:
    TFakeAlgorithm() : IAlgorithm(nullptr) {}
    void RemoveSelected(IBackend*) noexcept override {}
    void Reset() noexcept override {}
    IBackend* Next() noexcept override {
        return nullptr;
    }
};

struct TBackendsGroupWeights {
    double WeightsSum = 0;
    TVector<std::pair<double, size_t>> BoundaryAndIndex;
    void Add(double weight, size_t index);
    void Clear() noexcept;
};

}  // namespace NSrvKernel
