// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Code generated by Microsoft (R) TypeSpec Code Generator.

package tsptest.optional;

import com.azure.core.annotation.Generated;
import com.azure.core.annotation.ReturnType;
import com.azure.core.annotation.ServiceClient;
import com.azure.core.annotation.ServiceMethod;
import com.azure.core.exception.ClientAuthenticationException;
import com.azure.core.exception.HttpResponseException;
import com.azure.core.exception.ResourceModifiedException;
import com.azure.core.exception.ResourceNotFoundException;
import com.azure.core.http.HttpHeaderName;
import com.azure.core.http.rest.RequestOptions;
import com.azure.core.http.rest.Response;
import com.azure.core.util.BinaryData;
import com.azure.core.util.FluxUtil;
import reactor.core.publisher.Mono;
import tsptest.optional.implementation.OptionalOpsImpl;
import tsptest.optional.models.AllPropertiesOptional;
import tsptest.optional.models.Optional;

/**
 * Initializes a new instance of the asynchronous OptionalClient type.
 */
@ServiceClient(builder = OptionalClientBuilder.class, isAsync = true)
public final class OptionalAsyncClient {
    @Generated
    private final OptionalOpsImpl serviceClient;

    /**
     * Initializes an instance of OptionalAsyncClient class.
     * 
     * @param serviceClient the service client implementation.
     */
    @Generated
    OptionalAsyncClient(OptionalOpsImpl serviceClient) {
        this.serviceClient = serviceClient;
    }

    /**
     * The put operation.
     * <p><strong>Query Parameters</strong></p>
     * <table border="1">
     * <caption>Query Parameters</caption>
     * <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>
     * <tr><td>booleanNullable</td><td>Boolean</td><td>No</td><td>The booleanNullable parameter</td></tr>
     * <tr><td>string</td><td>String</td><td>No</td><td>The string parameter</td></tr>
     * <tr><td>stringNullable</td><td>String</td><td>No</td><td>The stringNullable parameter</td></tr>
     * </table>
     * You can add these to a request with {@link RequestOptions#addQueryParam}
     * <p><strong>Header Parameters</strong></p>
     * <table border="1">
     * <caption>Header Parameters</caption>
     * <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>
     * <tr><td>Content-Type</td><td>String</td><td>No</td><td>The content type. Allowed values:
     * "application/json".</td></tr>
     * <tr><td>request-header-optional</td><td>String</td><td>No</td><td>The requestHeaderOptional parameter</td></tr>
     * </table>
     * You can add these to a request with {@link RequestOptions#addHeader}
     * <p><strong>Request Body Schema</strong></p>
     * 
     * <pre>
     * {@code
     * {
     *     boolean: Boolean (Optional)
     *     booleanNullable: Boolean (Optional)
     *     booleanRequired: boolean (Required)
     *     booleanRequiredNullable: Boolean (Required)
     *     string: String (Optional)
     *     stringNullable: String (Optional)
     *     stringRequired: String (Required)
     *     stringRequiredNullable: String (Required)
     *     bytes: byte[] (Optional)
     *     int: Integer (Optional)
     *     long: Long (Optional)
     *     float: Double (Optional)
     *     double: Double (Optional)
     *     duration: Duration (Optional)
     *     dateTime: OffsetDateTime (Optional)
     *     stringList (Optional): [
     *         String (Optional)
     *     ]
     *     bytesDict (Optional): {
     *         String: byte[] (Required)
     *     }
     *     epochDateTimeRequiredNullable: Long (Required)
     *     epochDateTimeNullable: Long (Optional)
     * }
     * }
     * </pre>
     * 
     * <p><strong>Response Body Schema</strong></p>
     * 
     * <pre>
     * {@code
     * {
     *     boolean: Boolean (Optional)
     *     booleanNullable: Boolean (Optional)
     *     booleanRequired: Boolean (Optional)
     *     booleanRequiredNullable: Boolean (Optional)
     *     string: String (Optional)
     *     stringNullable: String (Optional)
     *     stringRequired: String (Optional)
     *     stringRequiredNullable: String (Optional)
     *     bytes: byte[] (Optional)
     *     int: Integer (Optional)
     *     long: Long (Optional)
     *     float: Double (Optional)
     *     double: Double (Optional)
     *     duration: Duration (Optional)
     *     dateTime: OffsetDateTime (Optional)
     *     stringList (Optional): [
     *         String (Optional)
     *     ]
     *     bytesDict (Optional): {
     *         String: byte[] (Required)
     *     }
     *     epochDateTimeRequiredNullable: Long (Optional)
     *     epochDateTimeNullable: Long (Optional)
     *     immutable (Optional): {
     *         stringReadWriteRequired: String (Required)
     *         stringReadOnlyOptional: String (Optional)
     *     }
     * }
     * }
     * </pre>
     * 
     * @param requestHeaderRequired The requestHeaderRequired parameter.
     * @param booleanRequired The booleanRequired parameter.
     * @param booleanRequiredNullable The booleanRequiredNullable parameter.
     * @param stringRequired The stringRequired parameter.
     * @param stringRequiredNullable The stringRequiredNullable parameter.
     * @param requestOptions The options to configure the HTTP request before HTTP client sends it.
     * @throws HttpResponseException thrown if the request is rejected by server.
     * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401.
     * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404.
     * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409.
     * @return the response body along with {@link Response} on successful completion of {@link Mono}.
     */
    @Generated
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<Response<BinaryData>> putWithResponse(String requestHeaderRequired, boolean booleanRequired,
        Boolean booleanRequiredNullable, String stringRequired, String stringRequiredNullable,
        RequestOptions requestOptions) {
        return this.serviceClient.putWithResponseAsync(requestHeaderRequired, booleanRequired, booleanRequiredNullable,
            stringRequired, stringRequiredNullable, requestOptions);
    }

    /**
     * The put operation.
     * 
     * @param requestHeaderRequired The requestHeaderRequired parameter.
     * @param booleanRequired The booleanRequired parameter.
     * @param booleanRequiredNullable The booleanRequiredNullable parameter.
     * @param stringRequired The stringRequired parameter.
     * @param stringRequiredNullable The stringRequiredNullable parameter.
     * @param requestHeaderOptional The requestHeaderOptional parameter.
     * @param booleanNullable The booleanNullable parameter.
     * @param string The string parameter.
     * @param stringNullable The stringNullable parameter.
     * @param optional The optional parameter.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws HttpResponseException thrown if the request is rejected by server.
     * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401.
     * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404.
     * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return the response body on successful completion of {@link Mono}.
     */
    @Generated
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<AllPropertiesOptional> put(String requestHeaderRequired, boolean booleanRequired,
        Boolean booleanRequiredNullable, String stringRequired, String stringRequiredNullable,
        String requestHeaderOptional, Boolean booleanNullable, String string, String stringNullable,
        Optional optional) {
        // Generated convenience method for putWithResponse
        RequestOptions requestOptions = new RequestOptions();
        if (requestHeaderOptional != null) {
            requestOptions.setHeader(HttpHeaderName.fromString("request-header-optional"), requestHeaderOptional);
        }
        if (booleanNullable != null) {
            requestOptions.addQueryParam("booleanNullable", String.valueOf(booleanNullable), false);
        }
        if (string != null) {
            requestOptions.addQueryParam("string", string, false);
        }
        if (stringNullable != null) {
            requestOptions.addQueryParam("stringNullable", stringNullable, false);
        }
        if (optional != null) {
            requestOptions.setBody(BinaryData.fromObject(optional));
        }
        return putWithResponse(requestHeaderRequired, booleanRequired, booleanRequiredNullable, stringRequired,
            stringRequiredNullable, requestOptions).flatMap(FluxUtil::toMono)
                .map(protocolMethodData -> protocolMethodData.toObject(AllPropertiesOptional.class));
    }

    /**
     * The put operation.
     * 
     * @param requestHeaderRequired The requestHeaderRequired parameter.
     * @param booleanRequired The booleanRequired parameter.
     * @param booleanRequiredNullable The booleanRequiredNullable parameter.
     * @param stringRequired The stringRequired parameter.
     * @param stringRequiredNullable The stringRequiredNullable parameter.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws HttpResponseException thrown if the request is rejected by server.
     * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401.
     * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404.
     * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return the response body on successful completion of {@link Mono}.
     */
    @Generated
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<AllPropertiesOptional> put(String requestHeaderRequired, boolean booleanRequired,
        Boolean booleanRequiredNullable, String stringRequired, String stringRequiredNullable) {
        // Generated convenience method for putWithResponse
        RequestOptions requestOptions = new RequestOptions();
        return putWithResponse(requestHeaderRequired, booleanRequired, booleanRequiredNullable, stringRequired,
            stringRequiredNullable, requestOptions).flatMap(FluxUtil::toMono)
                .map(protocolMethodData -> protocolMethodData.toObject(AllPropertiesOptional.class));
    }
}
