/* Code generated by Azure.Iot.Operations.ProtocolCompilerLib v1.0.0.0; DO NOT EDIT. */

#nullable enable

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Azure.Iot.Operations.Protocol.Models;
using Azure.Iot.Operations.Protocol;
using Azure.Iot.Operations.Protocol.RPC;
using Azure.Iot.Operations.Protocol.Telemetry;
using Azure.Iot.Operations.Services.EdgeRegistry.Generated.Common;

namespace Azure.Iot.Operations.Services.EdgeRegistry.Generated
{
    [System.CodeDom.Compiler.GeneratedCode("Azure.Iot.Operations.ProtocolCompilerLib", "1.0.0.0")]
    public static partial class EdgeRegistry
    {
        public abstract partial class Client : IAsyncDisposable
        {
            private ApplicationContext applicationContext;
            private IMqttPubSubClient mqttClient;
            private readonly CreateGroupActionInvoker createGroupActionInvoker;
            private readonly GetGroupActionInvoker getGroupActionInvoker;
            private readonly ListGroupsActionInvoker listGroupsActionInvoker;
            private readonly DeleteGroupActionInvoker deleteGroupActionInvoker;
            private readonly CreateResourceActionInvoker createResourceActionInvoker;
            private readonly GetResourceActionInvoker getResourceActionInvoker;
            private readonly ListResourcesActionInvoker listResourcesActionInvoker;
            private readonly DeleteResourceActionInvoker deleteResourceActionInvoker;
            private readonly CreateVersionActionInvoker createVersionActionInvoker;
            private readonly GetVersionActionInvoker getVersionActionInvoker;
            private readonly ListVersionsActionInvoker listVersionsActionInvoker;
            private readonly DeleteVersionActionInvoker deleteVersionActionInvoker;

            /// <summary>
            /// Construct a new instance of this client.
            /// </summary>
            /// <param name="applicationContext">The shared context for your application.</param>
            /// <param name="mqttClient">The MQTT client to use.</param>
            /// <param name="topicTokenMap">
            /// The topic token replacement map to use for all operations by default. Generally, this will include the token values
            /// for topic tokens that should be the same for the duration of this client's lifetime.
            /// </param>
            public Client(ApplicationContext applicationContext, IMqttPubSubClient mqttClient, Dictionary<string, string>? topicTokenMap = null)
            {
                this.applicationContext = applicationContext;
                this.mqttClient = mqttClient;

                this.createGroupActionInvoker = new CreateGroupActionInvoker(applicationContext, mqttClient);
                this.getGroupActionInvoker = new GetGroupActionInvoker(applicationContext, mqttClient);
                this.listGroupsActionInvoker = new ListGroupsActionInvoker(applicationContext, mqttClient);
                this.deleteGroupActionInvoker = new DeleteGroupActionInvoker(applicationContext, mqttClient);
                this.createResourceActionInvoker = new CreateResourceActionInvoker(applicationContext, mqttClient);
                this.getResourceActionInvoker = new GetResourceActionInvoker(applicationContext, mqttClient);
                this.listResourcesActionInvoker = new ListResourcesActionInvoker(applicationContext, mqttClient);
                this.deleteResourceActionInvoker = new DeleteResourceActionInvoker(applicationContext, mqttClient);
                this.createVersionActionInvoker = new CreateVersionActionInvoker(applicationContext, mqttClient);
                this.getVersionActionInvoker = new GetVersionActionInvoker(applicationContext, mqttClient);
                this.listVersionsActionInvoker = new ListVersionsActionInvoker(applicationContext, mqttClient);
                this.deleteVersionActionInvoker = new DeleteVersionActionInvoker(applicationContext, mqttClient);

                if (topicTokenMap != null)
                {
                    foreach (string topicTokenKey in topicTokenMap.Keys)
                    {
                        this.createGroupActionInvoker.TopicTokenMap.TryAdd("ex:" + topicTokenKey, topicTokenMap[topicTokenKey]);
                        this.getGroupActionInvoker.TopicTokenMap.TryAdd("ex:" + topicTokenKey, topicTokenMap[topicTokenKey]);
                        this.listGroupsActionInvoker.TopicTokenMap.TryAdd("ex:" + topicTokenKey, topicTokenMap[topicTokenKey]);
                        this.deleteGroupActionInvoker.TopicTokenMap.TryAdd("ex:" + topicTokenKey, topicTokenMap[topicTokenKey]);
                        this.createResourceActionInvoker.TopicTokenMap.TryAdd("ex:" + topicTokenKey, topicTokenMap[topicTokenKey]);
                        this.getResourceActionInvoker.TopicTokenMap.TryAdd("ex:" + topicTokenKey, topicTokenMap[topicTokenKey]);
                        this.listResourcesActionInvoker.TopicTokenMap.TryAdd("ex:" + topicTokenKey, topicTokenMap[topicTokenKey]);
                        this.deleteResourceActionInvoker.TopicTokenMap.TryAdd("ex:" + topicTokenKey, topicTokenMap[topicTokenKey]);
                        this.createVersionActionInvoker.TopicTokenMap.TryAdd("ex:" + topicTokenKey, topicTokenMap[topicTokenKey]);
                        this.getVersionActionInvoker.TopicTokenMap.TryAdd("ex:" + topicTokenKey, topicTokenMap[topicTokenKey]);
                        this.listVersionsActionInvoker.TopicTokenMap.TryAdd("ex:" + topicTokenKey, topicTokenMap[topicTokenKey]);
                        this.deleteVersionActionInvoker.TopicTokenMap.TryAdd("ex:" + topicTokenKey, topicTokenMap[topicTokenKey]);
                    }
                }
            }

            public CreateGroupActionInvoker CreateGroupActionInvoker { get => this.createGroupActionInvoker; }

            public GetGroupActionInvoker GetGroupActionInvoker { get => this.getGroupActionInvoker; }

            public ListGroupsActionInvoker ListGroupsActionInvoker { get => this.listGroupsActionInvoker; }

            public DeleteGroupActionInvoker DeleteGroupActionInvoker { get => this.deleteGroupActionInvoker; }

            public CreateResourceActionInvoker CreateResourceActionInvoker { get => this.createResourceActionInvoker; }

            public GetResourceActionInvoker GetResourceActionInvoker { get => this.getResourceActionInvoker; }

            public ListResourcesActionInvoker ListResourcesActionInvoker { get => this.listResourcesActionInvoker; }

            public DeleteResourceActionInvoker DeleteResourceActionInvoker { get => this.deleteResourceActionInvoker; }

            public CreateVersionActionInvoker CreateVersionActionInvoker { get => this.createVersionActionInvoker; }

            public GetVersionActionInvoker GetVersionActionInvoker { get => this.getVersionActionInvoker; }

            public ListVersionsActionInvoker ListVersionsActionInvoker { get => this.listVersionsActionInvoker; }

            public DeleteVersionActionInvoker DeleteVersionActionInvoker { get => this.deleteVersionActionInvoker; }

            /// <summary>
            /// Invoke a command.
            /// </summary>
            /// <param name="request">The data for this command request.</param>
            /// <param name="requestMetadata">The metadata for this command request.</param>
            /// <param name="additionalTopicTokenMap">
            /// The topic token replacement map to use in addition to the topic tokens specified in the constructor. If this map
            /// contains any keys that the topic tokens specified in the constructor also has, then values specified in this map will take precedence.
            /// </param>
            /// <param name="commandTimeout">How long the command will be available on the broker for an executor to receive.</param>
            /// <param name="cancellationToken">Cancellation token.</param>
            /// <returns>The command response.</returns>
            public RpcCallAsync<CreateGroupOutputArguments> CreateGroupAsync(CreateGroupInputArguments request, CommandRequestMetadata? requestMetadata = null, Dictionary<string, string>? additionalTopicTokenMap = null, TimeSpan? commandTimeout = default, CancellationToken cancellationToken = default)
            {
                string? clientId = this.mqttClient.ClientId;
                if (string.IsNullOrEmpty(clientId))
                {
                    throw new InvalidOperationException("No MQTT client Id configured. Must connect to MQTT broker before invoking command.");
                }

                CommandRequestMetadata metadata = requestMetadata ?? new CommandRequestMetadata();
                additionalTopicTokenMap ??= new();

                Dictionary<string, string> prefixedAdditionalTopicTokenMap = new();
                foreach (string key in additionalTopicTokenMap.Keys)
                {
                    prefixedAdditionalTopicTokenMap["ex:" + key] = additionalTopicTokenMap[key];
                }

                prefixedAdditionalTopicTokenMap["invokerClientId"] = clientId;

                return new RpcCallAsync<CreateGroupOutputArguments>(this.CreateGroupInt(request, metadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken), metadata.CorrelationId);
            }

            /// <summary>
            /// Invoke a command.
            /// </summary>
            /// <param name="request">The data for this command request.</param>
            /// <param name="requestMetadata">The metadata for this command request.</param>
            /// <param name="additionalTopicTokenMap">
            /// The topic token replacement map to use in addition to the topic tokens specified in the constructor. If this map
            /// contains any keys that the topic tokens specified in the constructor also has, then values specified in this map will take precedence.
            /// </param>
            /// <param name="commandTimeout">How long the command will be available on the broker for an executor to receive.</param>
            /// <param name="cancellationToken">Cancellation token.</param>
            /// <returns>The command response.</returns>
            public RpcCallAsync<GetGroupOutputArguments> GetGroupAsync(GetGroupInputArguments request, CommandRequestMetadata? requestMetadata = null, Dictionary<string, string>? additionalTopicTokenMap = null, TimeSpan? commandTimeout = default, CancellationToken cancellationToken = default)
            {
                string? clientId = this.mqttClient.ClientId;
                if (string.IsNullOrEmpty(clientId))
                {
                    throw new InvalidOperationException("No MQTT client Id configured. Must connect to MQTT broker before invoking command.");
                }

                CommandRequestMetadata metadata = requestMetadata ?? new CommandRequestMetadata();
                additionalTopicTokenMap ??= new();

                Dictionary<string, string> prefixedAdditionalTopicTokenMap = new();
                foreach (string key in additionalTopicTokenMap.Keys)
                {
                    prefixedAdditionalTopicTokenMap["ex:" + key] = additionalTopicTokenMap[key];
                }

                prefixedAdditionalTopicTokenMap["invokerClientId"] = clientId;

                return new RpcCallAsync<GetGroupOutputArguments>(this.GetGroupInt(request, metadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken), metadata.CorrelationId);
            }

            /// <summary>
            /// Invoke a command.
            /// </summary>
            /// <param name="requestMetadata">The metadata for this command request.</param>
            /// <param name="additionalTopicTokenMap">
            /// The topic token replacement map to use in addition to the topic tokens specified in the constructor. If this map
            /// contains any keys that the topic tokens specified in the constructor also has, then values specified in this map will take precedence.
            /// </param>
            /// <param name="commandTimeout">How long the command will be available on the broker for an executor to receive.</param>
            /// <param name="cancellationToken">Cancellation token.</param>
            /// <returns>The command response.</returns>
            public RpcCallAsync<ListGroupsOutputArguments> ListGroupsAsync(CommandRequestMetadata? requestMetadata = null, Dictionary<string, string>? additionalTopicTokenMap = null, TimeSpan? commandTimeout = default, CancellationToken cancellationToken = default)
            {
                string? clientId = this.mqttClient.ClientId;
                if (string.IsNullOrEmpty(clientId))
                {
                    throw new InvalidOperationException("No MQTT client Id configured. Must connect to MQTT broker before invoking command.");
                }

                CommandRequestMetadata metadata = requestMetadata ?? new CommandRequestMetadata();
                additionalTopicTokenMap ??= new();

                Dictionary<string, string> prefixedAdditionalTopicTokenMap = new();
                foreach (string key in additionalTopicTokenMap.Keys)
                {
                    prefixedAdditionalTopicTokenMap["ex:" + key] = additionalTopicTokenMap[key];
                }

                prefixedAdditionalTopicTokenMap["invokerClientId"] = clientId;

                return new RpcCallAsync<ListGroupsOutputArguments>(this.ListGroupsInt(new EmptyJson(), metadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken), metadata.CorrelationId);
            }

            /// <summary>
            /// Invoke a command.
            /// </summary>
            /// <param name="request">The data for this command request.</param>
            /// <param name="requestMetadata">The metadata for this command request.</param>
            /// <param name="additionalTopicTokenMap">
            /// The topic token replacement map to use in addition to the topic tokens specified in the constructor. If this map
            /// contains any keys that the topic tokens specified in the constructor also has, then values specified in this map will take precedence.
            /// </param>
            /// <param name="commandTimeout">How long the command will be available on the broker for an executor to receive.</param>
            /// <param name="cancellationToken">Cancellation token.</param>
            /// <returns>The command response.</returns>
            public RpcCallAsync<EmptyJson> DeleteGroupAsync(DeleteGroupInputArguments request, CommandRequestMetadata? requestMetadata = null, Dictionary<string, string>? additionalTopicTokenMap = null, TimeSpan? commandTimeout = default, CancellationToken cancellationToken = default)
            {
                string? clientId = this.mqttClient.ClientId;
                if (string.IsNullOrEmpty(clientId))
                {
                    throw new InvalidOperationException("No MQTT client Id configured. Must connect to MQTT broker before invoking command.");
                }

                CommandRequestMetadata metadata = requestMetadata ?? new CommandRequestMetadata();
                additionalTopicTokenMap ??= new();

                Dictionary<string, string> prefixedAdditionalTopicTokenMap = new();
                foreach (string key in additionalTopicTokenMap.Keys)
                {
                    prefixedAdditionalTopicTokenMap["ex:" + key] = additionalTopicTokenMap[key];
                }

                prefixedAdditionalTopicTokenMap["invokerClientId"] = clientId;

                return new RpcCallAsync<EmptyJson>(this.DeleteGroupInt(request, metadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken), metadata.CorrelationId);
            }

            /// <summary>
            /// Invoke a command.
            /// </summary>
            /// <param name="request">The data for this command request.</param>
            /// <param name="requestMetadata">The metadata for this command request.</param>
            /// <param name="additionalTopicTokenMap">
            /// The topic token replacement map to use in addition to the topic tokens specified in the constructor. If this map
            /// contains any keys that the topic tokens specified in the constructor also has, then values specified in this map will take precedence.
            /// </param>
            /// <param name="commandTimeout">How long the command will be available on the broker for an executor to receive.</param>
            /// <param name="cancellationToken">Cancellation token.</param>
            /// <returns>The command response.</returns>
            public RpcCallAsync<CreateResourceOutputArguments> CreateResourceAsync(CreateResourceInputArguments request, CommandRequestMetadata? requestMetadata = null, Dictionary<string, string>? additionalTopicTokenMap = null, TimeSpan? commandTimeout = default, CancellationToken cancellationToken = default)
            {
                string? clientId = this.mqttClient.ClientId;
                if (string.IsNullOrEmpty(clientId))
                {
                    throw new InvalidOperationException("No MQTT client Id configured. Must connect to MQTT broker before invoking command.");
                }

                CommandRequestMetadata metadata = requestMetadata ?? new CommandRequestMetadata();
                additionalTopicTokenMap ??= new();

                Dictionary<string, string> prefixedAdditionalTopicTokenMap = new();
                foreach (string key in additionalTopicTokenMap.Keys)
                {
                    prefixedAdditionalTopicTokenMap["ex:" + key] = additionalTopicTokenMap[key];
                }

                prefixedAdditionalTopicTokenMap["invokerClientId"] = clientId;

                return new RpcCallAsync<CreateResourceOutputArguments>(this.CreateResourceInt(request, metadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken), metadata.CorrelationId);
            }

            /// <summary>
            /// Invoke a command.
            /// </summary>
            /// <param name="request">The data for this command request.</param>
            /// <param name="requestMetadata">The metadata for this command request.</param>
            /// <param name="additionalTopicTokenMap">
            /// The topic token replacement map to use in addition to the topic tokens specified in the constructor. If this map
            /// contains any keys that the topic tokens specified in the constructor also has, then values specified in this map will take precedence.
            /// </param>
            /// <param name="commandTimeout">How long the command will be available on the broker for an executor to receive.</param>
            /// <param name="cancellationToken">Cancellation token.</param>
            /// <returns>The command response.</returns>
            public RpcCallAsync<GetResourceOutputArguments> GetResourceAsync(GetResourceInputArguments request, CommandRequestMetadata? requestMetadata = null, Dictionary<string, string>? additionalTopicTokenMap = null, TimeSpan? commandTimeout = default, CancellationToken cancellationToken = default)
            {
                string? clientId = this.mqttClient.ClientId;
                if (string.IsNullOrEmpty(clientId))
                {
                    throw new InvalidOperationException("No MQTT client Id configured. Must connect to MQTT broker before invoking command.");
                }

                CommandRequestMetadata metadata = requestMetadata ?? new CommandRequestMetadata();
                additionalTopicTokenMap ??= new();

                Dictionary<string, string> prefixedAdditionalTopicTokenMap = new();
                foreach (string key in additionalTopicTokenMap.Keys)
                {
                    prefixedAdditionalTopicTokenMap["ex:" + key] = additionalTopicTokenMap[key];
                }

                prefixedAdditionalTopicTokenMap["invokerClientId"] = clientId;

                return new RpcCallAsync<GetResourceOutputArguments>(this.GetResourceInt(request, metadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken), metadata.CorrelationId);
            }

            /// <summary>
            /// Invoke a command.
            /// </summary>
            /// <param name="request">The data for this command request.</param>
            /// <param name="requestMetadata">The metadata for this command request.</param>
            /// <param name="additionalTopicTokenMap">
            /// The topic token replacement map to use in addition to the topic tokens specified in the constructor. If this map
            /// contains any keys that the topic tokens specified in the constructor also has, then values specified in this map will take precedence.
            /// </param>
            /// <param name="commandTimeout">How long the command will be available on the broker for an executor to receive.</param>
            /// <param name="cancellationToken">Cancellation token.</param>
            /// <returns>The command response.</returns>
            public RpcCallAsync<ListResourcesOutputArguments> ListResourcesAsync(ListResourcesInputArguments request, CommandRequestMetadata? requestMetadata = null, Dictionary<string, string>? additionalTopicTokenMap = null, TimeSpan? commandTimeout = default, CancellationToken cancellationToken = default)
            {
                string? clientId = this.mqttClient.ClientId;
                if (string.IsNullOrEmpty(clientId))
                {
                    throw new InvalidOperationException("No MQTT client Id configured. Must connect to MQTT broker before invoking command.");
                }

                CommandRequestMetadata metadata = requestMetadata ?? new CommandRequestMetadata();
                additionalTopicTokenMap ??= new();

                Dictionary<string, string> prefixedAdditionalTopicTokenMap = new();
                foreach (string key in additionalTopicTokenMap.Keys)
                {
                    prefixedAdditionalTopicTokenMap["ex:" + key] = additionalTopicTokenMap[key];
                }

                prefixedAdditionalTopicTokenMap["invokerClientId"] = clientId;

                return new RpcCallAsync<ListResourcesOutputArguments>(this.ListResourcesInt(request, metadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken), metadata.CorrelationId);
            }

            /// <summary>
            /// Invoke a command.
            /// </summary>
            /// <param name="request">The data for this command request.</param>
            /// <param name="requestMetadata">The metadata for this command request.</param>
            /// <param name="additionalTopicTokenMap">
            /// The topic token replacement map to use in addition to the topic tokens specified in the constructor. If this map
            /// contains any keys that the topic tokens specified in the constructor also has, then values specified in this map will take precedence.
            /// </param>
            /// <param name="commandTimeout">How long the command will be available on the broker for an executor to receive.</param>
            /// <param name="cancellationToken">Cancellation token.</param>
            /// <returns>The command response.</returns>
            public RpcCallAsync<EmptyJson> DeleteResourceAsync(DeleteResourceInputArguments request, CommandRequestMetadata? requestMetadata = null, Dictionary<string, string>? additionalTopicTokenMap = null, TimeSpan? commandTimeout = default, CancellationToken cancellationToken = default)
            {
                string? clientId = this.mqttClient.ClientId;
                if (string.IsNullOrEmpty(clientId))
                {
                    throw new InvalidOperationException("No MQTT client Id configured. Must connect to MQTT broker before invoking command.");
                }

                CommandRequestMetadata metadata = requestMetadata ?? new CommandRequestMetadata();
                additionalTopicTokenMap ??= new();

                Dictionary<string, string> prefixedAdditionalTopicTokenMap = new();
                foreach (string key in additionalTopicTokenMap.Keys)
                {
                    prefixedAdditionalTopicTokenMap["ex:" + key] = additionalTopicTokenMap[key];
                }

                prefixedAdditionalTopicTokenMap["invokerClientId"] = clientId;

                return new RpcCallAsync<EmptyJson>(this.DeleteResourceInt(request, metadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken), metadata.CorrelationId);
            }

            /// <summary>
            /// Invoke a command.
            /// </summary>
            /// <param name="request">The data for this command request.</param>
            /// <param name="requestMetadata">The metadata for this command request.</param>
            /// <param name="additionalTopicTokenMap">
            /// The topic token replacement map to use in addition to the topic tokens specified in the constructor. If this map
            /// contains any keys that the topic tokens specified in the constructor also has, then values specified in this map will take precedence.
            /// </param>
            /// <param name="commandTimeout">How long the command will be available on the broker for an executor to receive.</param>
            /// <param name="cancellationToken">Cancellation token.</param>
            /// <returns>The command response.</returns>
            public RpcCallAsync<CreateVersionOutputArguments> CreateVersionAsync(CreateVersionInputArguments request, CommandRequestMetadata? requestMetadata = null, Dictionary<string, string>? additionalTopicTokenMap = null, TimeSpan? commandTimeout = default, CancellationToken cancellationToken = default)
            {
                string? clientId = this.mqttClient.ClientId;
                if (string.IsNullOrEmpty(clientId))
                {
                    throw new InvalidOperationException("No MQTT client Id configured. Must connect to MQTT broker before invoking command.");
                }

                CommandRequestMetadata metadata = requestMetadata ?? new CommandRequestMetadata();
                additionalTopicTokenMap ??= new();

                Dictionary<string, string> prefixedAdditionalTopicTokenMap = new();
                foreach (string key in additionalTopicTokenMap.Keys)
                {
                    prefixedAdditionalTopicTokenMap["ex:" + key] = additionalTopicTokenMap[key];
                }

                prefixedAdditionalTopicTokenMap["invokerClientId"] = clientId;

                return new RpcCallAsync<CreateVersionOutputArguments>(this.CreateVersionInt(request, metadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken), metadata.CorrelationId);
            }

            /// <summary>
            /// Invoke a command.
            /// </summary>
            /// <param name="request">The data for this command request.</param>
            /// <param name="requestMetadata">The metadata for this command request.</param>
            /// <param name="additionalTopicTokenMap">
            /// The topic token replacement map to use in addition to the topic tokens specified in the constructor. If this map
            /// contains any keys that the topic tokens specified in the constructor also has, then values specified in this map will take precedence.
            /// </param>
            /// <param name="commandTimeout">How long the command will be available on the broker for an executor to receive.</param>
            /// <param name="cancellationToken">Cancellation token.</param>
            /// <returns>The command response.</returns>
            public RpcCallAsync<GetVersionOutputArguments> GetVersionAsync(GetVersionInputArguments request, CommandRequestMetadata? requestMetadata = null, Dictionary<string, string>? additionalTopicTokenMap = null, TimeSpan? commandTimeout = default, CancellationToken cancellationToken = default)
            {
                string? clientId = this.mqttClient.ClientId;
                if (string.IsNullOrEmpty(clientId))
                {
                    throw new InvalidOperationException("No MQTT client Id configured. Must connect to MQTT broker before invoking command.");
                }

                CommandRequestMetadata metadata = requestMetadata ?? new CommandRequestMetadata();
                additionalTopicTokenMap ??= new();

                Dictionary<string, string> prefixedAdditionalTopicTokenMap = new();
                foreach (string key in additionalTopicTokenMap.Keys)
                {
                    prefixedAdditionalTopicTokenMap["ex:" + key] = additionalTopicTokenMap[key];
                }

                prefixedAdditionalTopicTokenMap["invokerClientId"] = clientId;

                return new RpcCallAsync<GetVersionOutputArguments>(this.GetVersionInt(request, metadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken), metadata.CorrelationId);
            }

            /// <summary>
            /// Invoke a command.
            /// </summary>
            /// <param name="request">The data for this command request.</param>
            /// <param name="requestMetadata">The metadata for this command request.</param>
            /// <param name="additionalTopicTokenMap">
            /// The topic token replacement map to use in addition to the topic tokens specified in the constructor. If this map
            /// contains any keys that the topic tokens specified in the constructor also has, then values specified in this map will take precedence.
            /// </param>
            /// <param name="commandTimeout">How long the command will be available on the broker for an executor to receive.</param>
            /// <param name="cancellationToken">Cancellation token.</param>
            /// <returns>The command response.</returns>
            public RpcCallAsync<ListVersionsOutputArguments> ListVersionsAsync(ListVersionsInputArguments request, CommandRequestMetadata? requestMetadata = null, Dictionary<string, string>? additionalTopicTokenMap = null, TimeSpan? commandTimeout = default, CancellationToken cancellationToken = default)
            {
                string? clientId = this.mqttClient.ClientId;
                if (string.IsNullOrEmpty(clientId))
                {
                    throw new InvalidOperationException("No MQTT client Id configured. Must connect to MQTT broker before invoking command.");
                }

                CommandRequestMetadata metadata = requestMetadata ?? new CommandRequestMetadata();
                additionalTopicTokenMap ??= new();

                Dictionary<string, string> prefixedAdditionalTopicTokenMap = new();
                foreach (string key in additionalTopicTokenMap.Keys)
                {
                    prefixedAdditionalTopicTokenMap["ex:" + key] = additionalTopicTokenMap[key];
                }

                prefixedAdditionalTopicTokenMap["invokerClientId"] = clientId;

                return new RpcCallAsync<ListVersionsOutputArguments>(this.ListVersionsInt(request, metadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken), metadata.CorrelationId);
            }

            /// <summary>
            /// Invoke a command.
            /// </summary>
            /// <param name="request">The data for this command request.</param>
            /// <param name="requestMetadata">The metadata for this command request.</param>
            /// <param name="additionalTopicTokenMap">
            /// The topic token replacement map to use in addition to the topic tokens specified in the constructor. If this map
            /// contains any keys that the topic tokens specified in the constructor also has, then values specified in this map will take precedence.
            /// </param>
            /// <param name="commandTimeout">How long the command will be available on the broker for an executor to receive.</param>
            /// <param name="cancellationToken">Cancellation token.</param>
            /// <returns>The command response.</returns>
            public RpcCallAsync<EmptyJson> DeleteVersionAsync(DeleteVersionInputArguments request, CommandRequestMetadata? requestMetadata = null, Dictionary<string, string>? additionalTopicTokenMap = null, TimeSpan? commandTimeout = default, CancellationToken cancellationToken = default)
            {
                string? clientId = this.mqttClient.ClientId;
                if (string.IsNullOrEmpty(clientId))
                {
                    throw new InvalidOperationException("No MQTT client Id configured. Must connect to MQTT broker before invoking command.");
                }

                CommandRequestMetadata metadata = requestMetadata ?? new CommandRequestMetadata();
                additionalTopicTokenMap ??= new();

                Dictionary<string, string> prefixedAdditionalTopicTokenMap = new();
                foreach (string key in additionalTopicTokenMap.Keys)
                {
                    prefixedAdditionalTopicTokenMap["ex:" + key] = additionalTopicTokenMap[key];
                }

                prefixedAdditionalTopicTokenMap["invokerClientId"] = clientId;

                return new RpcCallAsync<EmptyJson>(this.DeleteVersionInt(request, metadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken), metadata.CorrelationId);
            }

            /// <summary>
            /// Stop accepting telemetry for all telemetry receivers and make all command invokers unsubscribe from command topics.
            /// </summary>
            /// <param name="cancellationToken">Cancellation token.</param>
            public async Task StopAsync(CancellationToken cancellationToken = default)
            {
                await Task.WhenAll(
                    this.createGroupActionInvoker.StopAsync(cancellationToken),
                    this.getGroupActionInvoker.StopAsync(cancellationToken),
                    this.listGroupsActionInvoker.StopAsync(cancellationToken),
                    this.deleteGroupActionInvoker.StopAsync(cancellationToken),
                    this.createResourceActionInvoker.StopAsync(cancellationToken),
                    this.getResourceActionInvoker.StopAsync(cancellationToken),
                    this.listResourcesActionInvoker.StopAsync(cancellationToken),
                    this.deleteResourceActionInvoker.StopAsync(cancellationToken),
                    this.createVersionActionInvoker.StopAsync(cancellationToken),
                    this.getVersionActionInvoker.StopAsync(cancellationToken),
                    this.listVersionsActionInvoker.StopAsync(cancellationToken),
                    this.deleteVersionActionInvoker.StopAsync(cancellationToken)).ConfigureAwait(false);
            }

            private async Task<ExtendedResponse<CreateGroupOutputArguments>> CreateGroupInt(CreateGroupInputArguments request, CommandRequestMetadata? requestMetadata, Dictionary<string, string>? prefixedAdditionalTopicTokenMap, TimeSpan? commandTimeout, CancellationToken cancellationToken)
            {
                ExtendedResponse<CreateGroupResponseSchema> extended = await this.createGroupActionInvoker.InvokeCommandAsync(request, requestMetadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken);

                if (extended.Response.Error != null)
                {
                    EdgeRegistryErrorException edgeRegistryErrorException = new EdgeRegistryErrorException(extended.Response.Error);
                    throw edgeRegistryErrorException;
                }
                else
                {
                    return new ExtendedResponse<CreateGroupOutputArguments>
                    {
                        Response = extended.Response.Output!,
                        ResponseMetadata = extended.ResponseMetadata,
                    };
                }
            }

            private async Task<ExtendedResponse<GetGroupOutputArguments>> GetGroupInt(GetGroupInputArguments request, CommandRequestMetadata? requestMetadata, Dictionary<string, string>? prefixedAdditionalTopicTokenMap, TimeSpan? commandTimeout, CancellationToken cancellationToken)
            {
                ExtendedResponse<GetGroupResponseSchema> extended = await this.getGroupActionInvoker.InvokeCommandAsync(request, requestMetadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken);

                if (extended.Response.Error != null)
                {
                    EdgeRegistryErrorException edgeRegistryErrorException = new EdgeRegistryErrorException(extended.Response.Error);
                    throw edgeRegistryErrorException;
                }
                else
                {
                    return new ExtendedResponse<GetGroupOutputArguments>
                    {
                        Response = extended.Response.Output!,
                        ResponseMetadata = extended.ResponseMetadata,
                    };
                }
            }

            private async Task<ExtendedResponse<ListGroupsOutputArguments>> ListGroupsInt(EmptyJson request, CommandRequestMetadata? requestMetadata, Dictionary<string, string>? prefixedAdditionalTopicTokenMap, TimeSpan? commandTimeout, CancellationToken cancellationToken)
            {
                ExtendedResponse<ListGroupsResponseSchema> extended = await this.listGroupsActionInvoker.InvokeCommandAsync(request, requestMetadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken);

                if (extended.Response.Error != null)
                {
                    EdgeRegistryErrorException edgeRegistryErrorException = new EdgeRegistryErrorException(extended.Response.Error);
                    throw edgeRegistryErrorException;
                }
                else
                {
                    return new ExtendedResponse<ListGroupsOutputArguments>
                    {
                        Response = new ListGroupsOutputArguments
                        {
                            Ids = extended.Response.Ids.Value(),
                        },
                        ResponseMetadata = extended.ResponseMetadata,
                    };
                }
            }

            private async Task<ExtendedResponse<EmptyJson>> DeleteGroupInt(DeleteGroupInputArguments request, CommandRequestMetadata? requestMetadata, Dictionary<string, string>? prefixedAdditionalTopicTokenMap, TimeSpan? commandTimeout, CancellationToken cancellationToken)
            {
                ExtendedResponse<DeleteGroupResponseSchema> extended = await this.deleteGroupActionInvoker.InvokeCommandAsync(request, requestMetadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken);

                if (extended.Response.Error != null)
                {
                    EdgeRegistryErrorException edgeRegistryErrorException = new EdgeRegistryErrorException(extended.Response.Error);
                    throw edgeRegistryErrorException;
                }
                else
                {
                    return new ExtendedResponse<EmptyJson>
                    {
                        Response = new EmptyJson
                        {
                        },
                        ResponseMetadata = extended.ResponseMetadata,
                    };
                }
            }

            private async Task<ExtendedResponse<CreateResourceOutputArguments>> CreateResourceInt(CreateResourceInputArguments request, CommandRequestMetadata? requestMetadata, Dictionary<string, string>? prefixedAdditionalTopicTokenMap, TimeSpan? commandTimeout, CancellationToken cancellationToken)
            {
                ExtendedResponse<CreateResourceResponseSchema> extended = await this.createResourceActionInvoker.InvokeCommandAsync(request, requestMetadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken);

                if (extended.Response.Error != null)
                {
                    EdgeRegistryErrorException edgeRegistryErrorException = new EdgeRegistryErrorException(extended.Response.Error);
                    throw edgeRegistryErrorException;
                }
                else
                {
                    return new ExtendedResponse<CreateResourceOutputArguments>
                    {
                        Response = extended.Response.Output!,
                        ResponseMetadata = extended.ResponseMetadata,
                    };
                }
            }

            private async Task<ExtendedResponse<GetResourceOutputArguments>> GetResourceInt(GetResourceInputArguments request, CommandRequestMetadata? requestMetadata, Dictionary<string, string>? prefixedAdditionalTopicTokenMap, TimeSpan? commandTimeout, CancellationToken cancellationToken)
            {
                ExtendedResponse<GetResourceResponseSchema> extended = await this.getResourceActionInvoker.InvokeCommandAsync(request, requestMetadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken);

                if (extended.Response.Error != null)
                {
                    EdgeRegistryErrorException edgeRegistryErrorException = new EdgeRegistryErrorException(extended.Response.Error);
                    throw edgeRegistryErrorException;
                }
                else
                {
                    return new ExtendedResponse<GetResourceOutputArguments>
                    {
                        Response = extended.Response.Output!,
                        ResponseMetadata = extended.ResponseMetadata,
                    };
                }
            }

            private async Task<ExtendedResponse<ListResourcesOutputArguments>> ListResourcesInt(ListResourcesInputArguments request, CommandRequestMetadata? requestMetadata, Dictionary<string, string>? prefixedAdditionalTopicTokenMap, TimeSpan? commandTimeout, CancellationToken cancellationToken)
            {
                ExtendedResponse<ListResourcesResponseSchema> extended = await this.listResourcesActionInvoker.InvokeCommandAsync(request, requestMetadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken);

                if (extended.Response.Error != null)
                {
                    EdgeRegistryErrorException edgeRegistryErrorException = new EdgeRegistryErrorException(extended.Response.Error);
                    throw edgeRegistryErrorException;
                }
                else
                {
                    return new ExtendedResponse<ListResourcesOutputArguments>
                    {
                        Response = extended.Response.Output!,
                        ResponseMetadata = extended.ResponseMetadata,
                    };
                }
            }

            private async Task<ExtendedResponse<EmptyJson>> DeleteResourceInt(DeleteResourceInputArguments request, CommandRequestMetadata? requestMetadata, Dictionary<string, string>? prefixedAdditionalTopicTokenMap, TimeSpan? commandTimeout, CancellationToken cancellationToken)
            {
                ExtendedResponse<DeleteResourceResponseSchema> extended = await this.deleteResourceActionInvoker.InvokeCommandAsync(request, requestMetadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken);

                if (extended.Response.Error != null)
                {
                    EdgeRegistryErrorException edgeRegistryErrorException = new EdgeRegistryErrorException(extended.Response.Error);
                    throw edgeRegistryErrorException;
                }
                else
                {
                    return new ExtendedResponse<EmptyJson>
                    {
                        Response = new EmptyJson
                        {
                        },
                        ResponseMetadata = extended.ResponseMetadata,
                    };
                }
            }

            private async Task<ExtendedResponse<CreateVersionOutputArguments>> CreateVersionInt(CreateVersionInputArguments request, CommandRequestMetadata? requestMetadata, Dictionary<string, string>? prefixedAdditionalTopicTokenMap, TimeSpan? commandTimeout, CancellationToken cancellationToken)
            {
                ExtendedResponse<CreateVersionResponseSchema> extended = await this.createVersionActionInvoker.InvokeCommandAsync(request, requestMetadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken);

                if (extended.Response.Error != null)
                {
                    EdgeRegistryErrorException edgeRegistryErrorException = new EdgeRegistryErrorException(extended.Response.Error);
                    throw edgeRegistryErrorException;
                }
                else
                {
                    return new ExtendedResponse<CreateVersionOutputArguments>
                    {
                        Response = extended.Response.Output!,
                        ResponseMetadata = extended.ResponseMetadata,
                    };
                }
            }

            private async Task<ExtendedResponse<GetVersionOutputArguments>> GetVersionInt(GetVersionInputArguments request, CommandRequestMetadata? requestMetadata, Dictionary<string, string>? prefixedAdditionalTopicTokenMap, TimeSpan? commandTimeout, CancellationToken cancellationToken)
            {
                ExtendedResponse<GetVersionResponseSchema> extended = await this.getVersionActionInvoker.InvokeCommandAsync(request, requestMetadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken);

                if (extended.Response.Error != null)
                {
                    EdgeRegistryErrorException edgeRegistryErrorException = new EdgeRegistryErrorException(extended.Response.Error);
                    throw edgeRegistryErrorException;
                }
                else
                {
                    return new ExtendedResponse<GetVersionOutputArguments>
                    {
                        Response = extended.Response.Output!,
                        ResponseMetadata = extended.ResponseMetadata,
                    };
                }
            }

            private async Task<ExtendedResponse<ListVersionsOutputArguments>> ListVersionsInt(ListVersionsInputArguments request, CommandRequestMetadata? requestMetadata, Dictionary<string, string>? prefixedAdditionalTopicTokenMap, TimeSpan? commandTimeout, CancellationToken cancellationToken)
            {
                ExtendedResponse<ListVersionsResponseSchema> extended = await this.listVersionsActionInvoker.InvokeCommandAsync(request, requestMetadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken);

                if (extended.Response.Error != null)
                {
                    EdgeRegistryErrorException edgeRegistryErrorException = new EdgeRegistryErrorException(extended.Response.Error);
                    throw edgeRegistryErrorException;
                }
                else
                {
                    return new ExtendedResponse<ListVersionsOutputArguments>
                    {
                        Response = extended.Response.Output!,
                        ResponseMetadata = extended.ResponseMetadata,
                    };
                }
            }

            private async Task<ExtendedResponse<EmptyJson>> DeleteVersionInt(DeleteVersionInputArguments request, CommandRequestMetadata? requestMetadata, Dictionary<string, string>? prefixedAdditionalTopicTokenMap, TimeSpan? commandTimeout, CancellationToken cancellationToken)
            {
                ExtendedResponse<DeleteVersionResponseSchema> extended = await this.deleteVersionActionInvoker.InvokeCommandAsync(request, requestMetadata, prefixedAdditionalTopicTokenMap, commandTimeout, cancellationToken);

                if (extended.Response.Error != null)
                {
                    EdgeRegistryErrorException edgeRegistryErrorException = new EdgeRegistryErrorException(extended.Response.Error);
                    throw edgeRegistryErrorException;
                }
                else
                {
                    return new ExtendedResponse<EmptyJson>
                    {
                        Response = new EmptyJson
                        {
                        },
                        ResponseMetadata = extended.ResponseMetadata,
                    };
                }
            }

            public async ValueTask DisposeAsync()
            {
                await this.createGroupActionInvoker.DisposeAsync().ConfigureAwait(false);
                await this.getGroupActionInvoker.DisposeAsync().ConfigureAwait(false);
                await this.listGroupsActionInvoker.DisposeAsync().ConfigureAwait(false);
                await this.deleteGroupActionInvoker.DisposeAsync().ConfigureAwait(false);
                await this.createResourceActionInvoker.DisposeAsync().ConfigureAwait(false);
                await this.getResourceActionInvoker.DisposeAsync().ConfigureAwait(false);
                await this.listResourcesActionInvoker.DisposeAsync().ConfigureAwait(false);
                await this.deleteResourceActionInvoker.DisposeAsync().ConfigureAwait(false);
                await this.createVersionActionInvoker.DisposeAsync().ConfigureAwait(false);
                await this.getVersionActionInvoker.DisposeAsync().ConfigureAwait(false);
                await this.listVersionsActionInvoker.DisposeAsync().ConfigureAwait(false);
                await this.deleteVersionActionInvoker.DisposeAsync().ConfigureAwait(false);
            }

            public async ValueTask DisposeAsync(bool disposing, CancellationToken cancellationToken = default)
            {
                await this.createGroupActionInvoker.DisposeAsync(disposing, cancellationToken).ConfigureAwait(false);
                await this.getGroupActionInvoker.DisposeAsync(disposing, cancellationToken).ConfigureAwait(false);
                await this.listGroupsActionInvoker.DisposeAsync(disposing, cancellationToken).ConfigureAwait(false);
                await this.deleteGroupActionInvoker.DisposeAsync(disposing, cancellationToken).ConfigureAwait(false);
                await this.createResourceActionInvoker.DisposeAsync(disposing, cancellationToken).ConfigureAwait(false);
                await this.getResourceActionInvoker.DisposeAsync(disposing, cancellationToken).ConfigureAwait(false);
                await this.listResourcesActionInvoker.DisposeAsync(disposing, cancellationToken).ConfigureAwait(false);
                await this.deleteResourceActionInvoker.DisposeAsync(disposing, cancellationToken).ConfigureAwait(false);
                await this.createVersionActionInvoker.DisposeAsync(disposing, cancellationToken).ConfigureAwait(false);
                await this.getVersionActionInvoker.DisposeAsync(disposing, cancellationToken).ConfigureAwait(false);
                await this.listVersionsActionInvoker.DisposeAsync(disposing, cancellationToken).ConfigureAwait(false);
                await this.deleteVersionActionInvoker.DisposeAsync(disposing, cancellationToken).ConfigureAwait(false);
            }
        }
    }
}
