public async Task ExecuteAsync(CommandContext context)
        {
            var client = new Ironclad.Client.Client
            {
                Id      = this.clientId,
                Enabled = true
            };

            await context.ClientsClient.ModifyClientAsync(client).ConfigureAwait(false);
        }
        public static void Configure(CommandLineApplication app, CommandLineOptions options, IConsole console)
        {
            // description
            app.Description      = "Creates a new client";
            app.ExtendedHelpText = $"{Environment.NewLine}Use 'clients add -i' to enter interactive mode{Environment.NewLine}";

            // arguments
            var argumentType     = app.Argument("type", "The type of client to add (allowed values are s[erver], w[ebsite], and c[onsole])", false);
            var argumentClientId = app.Argument("id", "The client identifier", false);

            // options
#pragma warning disable SA1025
            var optionName                        = app.Option("-n|--name <name>", "The name of the client", CommandOptionType.SingleValue);
            var optionSecret                      = app.Option("-s|--secret <secret>", "The client secret", CommandOptionType.SingleValue);
            var optionAllowedCorsOrigins          = app.Option("-c|--cors_uri <uri>", "An allowed CORS origin for the client (you can call this several times)", CommandOptionType.MultipleValue);
            var optionRedirectUris                = app.Option("-r|--redirect_uri <uri>", "A redirect URI for the client (you can call this several times)", CommandOptionType.MultipleValue);
            var optionPostLogoutRedirectUris      = app.Option("-l|--logout_uri <uri>", "A logout URI for the client (you can call this several times)", CommandOptionType.MultipleValue);
            var optionAllowedScopes               = app.Option("-a|--scope <scope>", "An allowed scope for the client (you can call this several times)", CommandOptionType.MultipleValue);
            var optionAccessTokenType             = app.Option("-t|--token_type <Jwt/Reference>", "The access token type for the client", CommandOptionType.SingleValue);
            var optionAllowedGrantTypes           = app.Option("-g|--grant_type <type>", "A grant type for the client (you can call this several times)", CommandOptionType.MultipleValue);
            var optionAllowAccessTokensViaBrowser = app.Option("-b|--browser", "Allow access tokens via browser", CommandOptionType.NoValue);
            var optionAllowOfflineAccess          = app.Option("-o|--offline", "Allow offline access", CommandOptionType.NoValue);
            var optionDoNotRequireClientSecret    = app.Option("-k|--no_secret", "Do not require client secret", CommandOptionType.NoValue);
            var optionRequirePkce                 = app.Option("-p|--pkce", "Require Proof Key for Code Exchange (PKCE)", CommandOptionType.NoValue);
            var optionDoNotRequireConsent         = app.Option("-q|--no_constent", "Do not require consent", CommandOptionType.NoValue);
            var optionDisabled                    = app.Option("-d|--disabled", "Creates the new client in a disabled state", CommandOptionType.NoValue);
            var optionInteractive                 = app.Option("-i|--interactive", "Enters interactive mode", CommandOptionType.NoValue);
#pragma warning restore SA1025

            app.HelpOption();

            // action (for this command)
            app.OnExecute(
                () =>
            {
                var reporter = new ConsoleReporter(console, options.Verbose.HasValue(), false);

                if (string.IsNullOrEmpty(argumentType.Value))
                {
                    // TODO (Cameron): Prompt for client type.
                    reporter.Warn("The type of client is required. Allowed values are s[erver], w[ebsite], and c[onsole].");
                    return;
                }

                var helper = default(IHelper <IroncladClient>);
                switch (argumentType.Value?.ToUpperInvariant())
                {
                case "S":
                case "SERVER":
                    helper = new ServerClientHelper();
                    break;

                case "W":
                case "WEBSITE":
                    helper = new WebsiteClientHelper();
                    break;

                case "C":
                case "CONSOLE":
                    helper = new ConsoleClientHelper();
                    break;

                case null:
                default:
                    if (!optionInteractive.HasValue())
                    {
                        app.ShowVersionAndHelp();
                        return;
                    }
                    break;
                }

#pragma warning disable CA1308
                reporter.Verbose(
                    $"Command type configured for '{helper.GetType().Name.ToLowerInvariant().Replace("ClientHelper", string.Empty, StringComparison.OrdinalIgnoreCase)}'.");
#pragma warning restore CA1308

                var client = helper.GetPrototype(
                    new IroncladClient
                {
                    Id                          = argumentClientId.Value,
                    Secret                      = optionSecret.Value(),
                    Name                        = optionName.Value(),
                    AccessTokenType             = optionAccessTokenType.Value(),
                    AllowedCorsOrigins          = optionAllowedCorsOrigins.HasValue() ? optionAllowedCorsOrigins.Values.Distinct().ToHashSet() : null,
                    RedirectUris                = optionRedirectUris.HasValue() ? optionRedirectUris.Values.Distinct().ToHashSet() : null,
                    PostLogoutRedirectUris      = optionPostLogoutRedirectUris.HasValue() ? optionPostLogoutRedirectUris.Values.Distinct().ToHashSet() : null,
                    AllowedScopes               = optionAllowedScopes.HasValue() ? optionAllowedScopes.Values.Distinct().ToHashSet() : null,
                    AllowedGrantTypes           = optionAllowedGrantTypes.HasValue() ? optionAllowedGrantTypes.Values.Distinct().ToHashSet() : null,
                    AllowAccessTokensViaBrowser = optionAllowAccessTokensViaBrowser.HasValue() ? (bool?)true : null,
                    AllowOfflineAccess          = optionAllowOfflineAccess.HasValue() ? (bool?)true : null,
                    RequirePkce                 = optionRequirePkce.HasValue() ? (bool?)true : null,
                    RequireClientSecret         = optionDoNotRequireClientSecret.HasValue() ? (bool?)false : null,
                    RequireConsent              = optionDoNotRequireConsent.HasValue() ? (bool?)false : null,
                    Enabled                     = optionDisabled.HasValue() ? (bool?)false : null,
                });

                reporter.Verbose("Prototype client (from command line arguments):");
                reporter.Verbose(JsonConvert.SerializeObject(client));

                if (!helper.IsValid(client) || optionInteractive.HasValue())
                {
                    try
                    {
                        client = helper.GetValid(client);
                    }
                    catch (NotSupportedException ex)
                    {
                        throw new CommandParsingException(app, $"Operation Aborted. {ex.Message}", ex);
                    }

                    reporter.Verbose("Validated client (from interactive console):");
                    reporter.Verbose(JsonConvert.SerializeObject(client));
                }

                options.Command = new AddClientCommand {
                    client = client
                };
            });
        }