#pragma once

#include <saas/library/persqueue/configuration/proto/types.pb.h>

#include <library/cpp/getopt/small/last_getopt.h>
#include <library/cpp/logger/global/global.h>

#include <util/string/vector.h>
#include <util/folder/dirut.h>

namespace NSaasLB {
    class IOptions {
    public:
        void Init();
        void Parse(const TString& program, int argc, char* argv[]);
        void PrintUsage(const TString& program) const;

    protected:
        virtual void AddToParsing();

    private:
        void InitGlobalLog();

    protected:
        NLastGetopt::TOpts Parser;
        std::optional<NLastGetopt::TOptsParseResultException> ParsingResult;

    private:
        TString GlobalLog;
        ELogPriority LogLevel;
    };

    class TModifyOptions : virtual public IOptions {
    public:
        bool GetDryRun() const;
        bool GetSkipConfirm() const;

    protected:
        void AddToParsing() override;
        void DoAddToParsing();
    };

    class TNamespaceOptions : virtual public IOptions {
    public:
        TString GetName() const;

    protected:
        void AddToParsing() override;
        void DoAddToParsing();

    protected:
        TString Name;
    };

    class TCommonModifyNamespaceOptions
        : public TNamespaceOptions
        , public TModifyOptions
    {
    public:
        using TBase = TNamespaceOptions::IOptions;

    protected:
        void AddToParsing() override;
    };

    class TModifyNamespaceOptions : public TCommonModifyNamespaceOptions {
    public:
        TString GetLogbrokerServicesPath() const;
        TString GetLocksServer() const;
        TString GetLocksPath() const;
        std::optional<TString> GetServicesConfigsPath() const;
        std::optional<TString> GetDeployManagerHost() const;
        std::optional<TString> GetDevConsumersPath() const;

    protected:
        void AddToParsing() override;

    private:
        TString LogbrokerPath;
        TString LocksServer;
        TString LocksPath;
    };

    class TServiceOptions : virtual public IOptions {
    public:
        TString GetNamespace() const;
        TString GetService() const;
        TString GetCtype() const;
        std::optional<TString> GetGencfgTag() const;

    protected:
        void AddToParsing() override;
        void DoAddToParsing();

    private:
        TString Namespace;
        TString Service;
        TString Ctype;
    };

    class TDescribeServiceOptions : public TServiceOptions {
    public:
        bool GetShowLocks() const;

    protected:
        void AddToParsing() override;
    };

    class TModifyServiceOptions
        : public TServiceOptions
        , public TModifyOptions
    {
    public:
        using TBase = TServiceOptions::IOptions;
    public:
        bool GetNoRemove() const;
        bool GetForceRemove() const;

    protected:
        void AddToParsing() override;
    };

    class TUpdateTopicsOptions : virtual public TModifyServiceOptions {
    public:
        std::optional<TVector<TString>> GetShards() const;

    protected:
        void AddToParsing() override;

        void DoAddToParsing();
    };

    class TUpdateConsumersOptions : virtual public TModifyServiceOptions {
    public:
        std::optional<ui32> GetReplicas() const;

    protected:
        void AddToParsing() override;
        void DoAddToParsing();
    };

    class TCreateServiceOptions
        : public TUpdateConsumersOptions
        , public TUpdateTopicsOptions
    {
    public:
        using TBase = TUpdateConsumersOptions::TModifyServiceOptions;
    public:
        ELogbrokerName GetLogbrokerName() const;
        TVector<ui32> GetTvmWrite() const;
        TVector<ui32> GetTvmRead() const;
        TVector<TString> GetYtDeliveryClusters() const;
        std::optional<TString> GetLocksPath() const;
        std::optional<TString> GetTopicsPath() const;
        std::optional<TString> GetConsumersPath() const;
        TVector<EDataCenter> GetDataCenters() const;
        std::optional<TVector<TString>> GetGencfgGroups() const;
        std::optional<TString> GetDeployManagerHost() const;

        std::optional<ELogbrokerName> GetLogbrokerMirrorName() const;
        std::optional<TString> GetMirrorTopicsPath() const;
        std::optional<TString> GetMirrorConsumersPath() const;

    protected:
        void AddToParsing() override;
    };

    class TModifyPermissionsOptions : public TModifyServiceOptions {
    public:
        TVector<ui32> GetTvmIds() const;

    protected:
        void AddToParsing() override;
    };
}
