#pragma once

#include <library/cpp/config/sax.h>

#include <util/generic/maybe.h>

namespace NBalancerSD {

    struct TConfigNode {
        TMaybe<bool> AsBool;
        TMaybe<TString> AsString;

        THashMap<TString, TConfigNode> NestedNodes;
        bool IsContainer = false;
    public:
        TConfigNode& operator[](TStringBuf key) {
            IsContainer = true;
            return NestedNodes[key];
        }
    };

    TConfigNode Save(NConfig::IConfig& config);
    THolder<NConfig::IConfig> Restore(const TConfigNode& saved);

    struct TBackend {
        TString Host;
        TString Ip;
        ui32 Port = 0;
        bool Ready = false;
        TMaybe<double> Weight;

        bool operator==(const TBackend& other) const noexcept {
            return Host == other.Host && Ip == other.Ip && Port == other.Port;
        }

        bool operator!=(const TBackend& other) const noexcept {
            return !(*this == other);
        }
    };

    struct TEndpointSetBackends {
        TString EndpointSetKey;
        TVector<TBackend> Backends;
    };

    TString MakeUniqueBackendName(const TString& endpointSetKey, const TBackend& backend);

    TVector<TEndpointSetBackends> ParseBackends(NConfig::IConfig& config);

    THolder<NConfig::IConfig> MakeConfig(const TConfigNode& algoOpts,
                                        const TConfigNode& proxyOpts,
                                        const TConfigNode& proxyWrapper,
                                        ui16 overridenPort,
                                        i32 portOffset,
                                        const TVector<TEndpointSetBackends>& backends);
}
