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

package com.azure.iot.deviceupdate.implementation;

import com.azure.core.annotation.BodyParam;
import com.azure.core.annotation.Delete;
import com.azure.core.annotation.ExpectedResponses;
import com.azure.core.annotation.Get;
import com.azure.core.annotation.HeaderParam;
import com.azure.core.annotation.Host;
import com.azure.core.annotation.HostParam;
import com.azure.core.annotation.PathParam;
import com.azure.core.annotation.Post;
import com.azure.core.annotation.QueryParam;
import com.azure.core.annotation.ReturnType;
import com.azure.core.annotation.ServiceInterface;
import com.azure.core.annotation.ServiceMethod;
import com.azure.core.annotation.UnexpectedResponseExceptionType;
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.rest.PagedFlux;
import com.azure.core.http.rest.PagedIterable;
import com.azure.core.http.rest.PagedResponse;
import com.azure.core.http.rest.PagedResponseBase;
import com.azure.core.http.rest.RequestOptions;
import com.azure.core.http.rest.Response;
import com.azure.core.http.rest.RestProxy;
import com.azure.core.util.BinaryData;
import com.azure.core.util.Context;
import com.azure.core.util.FluxUtil;
import com.azure.core.util.polling.PollerFlux;
import com.azure.core.util.polling.SyncPoller;
import com.azure.core.util.serializer.TypeReference;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import reactor.core.publisher.Mono;

/** An instance of this class provides access to all the operations defined in DeviceUpdates. */
public final class DeviceUpdatesImpl {
    /** The proxy service used to perform REST calls. */
    private final DeviceUpdatesService service;

    /** The service client containing this operation class. */
    private final DeviceUpdateClientImpl client;

    /**
     * Initializes an instance of DeviceUpdatesImpl.
     *
     * @param client the instance of the service client containing this operation class.
     */
    DeviceUpdatesImpl(DeviceUpdateClientImpl client) {
        this.service =
                RestProxy.create(DeviceUpdatesService.class, client.getHttpPipeline(), client.getSerializerAdapter());
        this.client = client;
    }

    /**
     * The interface defining all the services for DeviceUpdateClientDeviceUpdates to be used by the proxy service to
     * perform REST calls.
     */
    @Host("https://{endpoint}")
    @ServiceInterface(name = "DeviceUpdateClientDe")
    public interface DeviceUpdatesService {
        @Get("/deviceUpdate/{instanceId}/updates")
        @ExpectedResponses({200})
        @UnexpectedResponseExceptionType(
                value = ClientAuthenticationException.class,
                code = {401})
        @UnexpectedResponseExceptionType(
                value = ResourceNotFoundException.class,
                code = {404})
        @UnexpectedResponseExceptionType(
                value = ResourceModifiedException.class,
                code = {409})
        @UnexpectedResponseExceptionType(HttpResponseException.class)
        Mono<Response<BinaryData>> listUpdates(
                @HostParam("endpoint") String endpoint,
                @PathParam(value = "instanceId", encoded = true) String instanceId,
                @QueryParam("api-version") String apiVersion,
                @HeaderParam("Accept") String accept,
                RequestOptions requestOptions,
                Context context);

        @Post("/deviceUpdate/{instanceId}/updates:import")
        @ExpectedResponses({200, 202})
        @UnexpectedResponseExceptionType(
                value = ClientAuthenticationException.class,
                code = {401})
        @UnexpectedResponseExceptionType(
                value = ResourceNotFoundException.class,
                code = {404})
        @UnexpectedResponseExceptionType(
                value = ResourceModifiedException.class,
                code = {409})
        @UnexpectedResponseExceptionType(HttpResponseException.class)
        Mono<Response<BinaryData>> importUpdate(
                @HostParam("endpoint") String endpoint,
                @PathParam(value = "instanceId", encoded = true) String instanceId,
                @QueryParam("api-version") String apiVersion,
                @BodyParam("application/json") BinaryData updateToImport,
                @HeaderParam("Accept") String accept,
                RequestOptions requestOptions,
                Context context);

        @Get("/deviceUpdate/{instanceId}/updates/providers/{provider}/names/{name}/versions/{version}")
        @ExpectedResponses({200})
        @UnexpectedResponseExceptionType(
                value = ClientAuthenticationException.class,
                code = {401})
        @UnexpectedResponseExceptionType(
                value = ResourceNotFoundException.class,
                code = {404})
        @UnexpectedResponseExceptionType(
                value = ResourceModifiedException.class,
                code = {409})
        @UnexpectedResponseExceptionType(HttpResponseException.class)
        Mono<Response<BinaryData>> getUpdate(
                @HostParam("endpoint") String endpoint,
                @PathParam(value = "instanceId", encoded = true) String instanceId,
                @PathParam("provider") String provider,
                @PathParam("name") String name,
                @PathParam("version") String version,
                @QueryParam("api-version") String apiVersion,
                @HeaderParam("Accept") String accept,
                RequestOptions requestOptions,
                Context context);

        @Delete("/deviceUpdate/{instanceId}/updates/providers/{provider}/names/{name}/versions/{version}")
        @ExpectedResponses({202})
        @UnexpectedResponseExceptionType(
                value = ClientAuthenticationException.class,
                code = {401})
        @UnexpectedResponseExceptionType(
                value = ResourceNotFoundException.class,
                code = {404})
        @UnexpectedResponseExceptionType(
                value = ResourceModifiedException.class,
                code = {409})
        @UnexpectedResponseExceptionType(HttpResponseException.class)
        Mono<Response<Void>> deleteUpdate(
                @HostParam("endpoint") String endpoint,
                @PathParam(value = "instanceId", encoded = true) String instanceId,
                @PathParam("provider") String provider,
                @PathParam("name") String name,
                @PathParam("version") String version,
                @QueryParam("api-version") String apiVersion,
                @HeaderParam("Accept") String accept,
                RequestOptions requestOptions,
                Context context);

        @Get("/deviceUpdate/{instanceId}/updates/providers")
        @ExpectedResponses({200})
        @UnexpectedResponseExceptionType(
                value = ClientAuthenticationException.class,
                code = {401})
        @UnexpectedResponseExceptionType(
                value = ResourceNotFoundException.class,
                code = {404})
        @UnexpectedResponseExceptionType(
                value = ResourceModifiedException.class,
                code = {409})
        @UnexpectedResponseExceptionType(HttpResponseException.class)
        Mono<Response<BinaryData>> listProviders(
                @HostParam("endpoint") String endpoint,
                @PathParam(value = "instanceId", encoded = true) String instanceId,
                @QueryParam("api-version") String apiVersion,
                @HeaderParam("Accept") String accept,
                RequestOptions requestOptions,
                Context context);

        @Get("/deviceUpdate/{instanceId}/updates/providers/{provider}/names")
        @ExpectedResponses({200})
        @UnexpectedResponseExceptionType(
                value = ClientAuthenticationException.class,
                code = {401})
        @UnexpectedResponseExceptionType(
                value = ResourceNotFoundException.class,
                code = {404})
        @UnexpectedResponseExceptionType(
                value = ResourceModifiedException.class,
                code = {409})
        @UnexpectedResponseExceptionType(HttpResponseException.class)
        Mono<Response<BinaryData>> listNames(
                @HostParam("endpoint") String endpoint,
                @PathParam(value = "instanceId", encoded = true) String instanceId,
                @PathParam("provider") String provider,
                @QueryParam("api-version") String apiVersion,
                @HeaderParam("Accept") String accept,
                RequestOptions requestOptions,
                Context context);

        @Get("/deviceUpdate/{instanceId}/updates/providers/{provider}/names/{name}/versions")
        @ExpectedResponses({200})
        @UnexpectedResponseExceptionType(
                value = ClientAuthenticationException.class,
                code = {401})
        @UnexpectedResponseExceptionType(
                value = ResourceNotFoundException.class,
                code = {404})
        @UnexpectedResponseExceptionType(
                value = ResourceModifiedException.class,
                code = {409})
        @UnexpectedResponseExceptionType(HttpResponseException.class)
        Mono<Response<BinaryData>> listVersions(
                @HostParam("endpoint") String endpoint,
                @PathParam(value = "instanceId", encoded = true) String instanceId,
                @PathParam("provider") String provider,
                @PathParam("name") String name,
                @QueryParam("api-version") String apiVersion,
                @HeaderParam("Accept") String accept,
                RequestOptions requestOptions,
                Context context);

        @Get("/deviceUpdate/{instanceId}/updates/providers/{provider}/names/{name}/versions/{version}/files")
        @ExpectedResponses({200})
        @UnexpectedResponseExceptionType(
                value = ClientAuthenticationException.class,
                code = {401})
        @UnexpectedResponseExceptionType(
                value = ResourceNotFoundException.class,
                code = {404})
        @UnexpectedResponseExceptionType(
                value = ResourceModifiedException.class,
                code = {409})
        @UnexpectedResponseExceptionType(HttpResponseException.class)
        Mono<Response<BinaryData>> listFiles(
                @HostParam("endpoint") String endpoint,
                @PathParam(value = "instanceId", encoded = true) String instanceId,
                @PathParam("provider") String provider,
                @PathParam("name") String name,
                @PathParam("version") String version,
                @QueryParam("api-version") String apiVersion,
                @HeaderParam("Accept") String accept,
                RequestOptions requestOptions,
                Context context);

        @Get("/deviceUpdate/{instanceId}/updates/providers/{provider}/names/{name}/versions/{version}/files/{fileId}")
        @ExpectedResponses({200})
        @UnexpectedResponseExceptionType(
                value = ClientAuthenticationException.class,
                code = {401})
        @UnexpectedResponseExceptionType(
                value = ResourceNotFoundException.class,
                code = {404})
        @UnexpectedResponseExceptionType(
                value = ResourceModifiedException.class,
                code = {409})
        @UnexpectedResponseExceptionType(HttpResponseException.class)
        Mono<Response<BinaryData>> getFile(
                @HostParam("endpoint") String endpoint,
                @PathParam(value = "instanceId", encoded = true) String instanceId,
                @PathParam("provider") String provider,
                @PathParam("name") String name,
                @PathParam("version") String version,
                @PathParam("fileId") String fileId,
                @QueryParam("api-version") String apiVersion,
                @HeaderParam("Accept") String accept,
                RequestOptions requestOptions,
                Context context);

        @Get("/deviceUpdate/{instanceId}/updates/operations")
        @ExpectedResponses({200})
        @UnexpectedResponseExceptionType(
                value = ClientAuthenticationException.class,
                code = {401})
        @UnexpectedResponseExceptionType(
                value = ResourceNotFoundException.class,
                code = {404})
        @UnexpectedResponseExceptionType(
                value = ResourceModifiedException.class,
                code = {409})
        @UnexpectedResponseExceptionType(HttpResponseException.class)
        Mono<Response<BinaryData>> listOperationStatuses(
                @HostParam("endpoint") String endpoint,
                @PathParam(value = "instanceId", encoded = true) String instanceId,
                @QueryParam("api-version") String apiVersion,
                @HeaderParam("Accept") String accept,
                RequestOptions requestOptions,
                Context context);

        @Get("/deviceUpdate/{instanceId}/updates/operations/{operationId}")
        @ExpectedResponses({200})
        @UnexpectedResponseExceptionType(
                value = ClientAuthenticationException.class,
                code = {401})
        @UnexpectedResponseExceptionType(
                value = ResourceNotFoundException.class,
                code = {404})
        @UnexpectedResponseExceptionType(
                value = ResourceModifiedException.class,
                code = {409})
        @UnexpectedResponseExceptionType(HttpResponseException.class)
        Mono<Response<BinaryData>> getOperationStatus(
                @HostParam("endpoint") String endpoint,
                @PathParam(value = "instanceId", encoded = true) String instanceId,
                @PathParam("operationId") String operationId,
                @QueryParam("api-version") String apiVersion,
                @HeaderParam("Accept") String accept,
                RequestOptions requestOptions,
                Context context);

        @Get("{nextLink}")
        @ExpectedResponses({200})
        @UnexpectedResponseExceptionType(
                value = ClientAuthenticationException.class,
                code = {401})
        @UnexpectedResponseExceptionType(
                value = ResourceNotFoundException.class,
                code = {404})
        @UnexpectedResponseExceptionType(
                value = ResourceModifiedException.class,
                code = {409})
        @UnexpectedResponseExceptionType(HttpResponseException.class)
        Mono<Response<BinaryData>> listUpdatesNext(
                @PathParam(value = "nextLink", encoded = true) String nextLink,
                @HostParam("endpoint") String endpoint,
                @HeaderParam("Accept") String accept,
                RequestOptions requestOptions,
                Context context);

        @Get("{nextLink}")
        @ExpectedResponses({200})
        @UnexpectedResponseExceptionType(
                value = ClientAuthenticationException.class,
                code = {401})
        @UnexpectedResponseExceptionType(
                value = ResourceNotFoundException.class,
                code = {404})
        @UnexpectedResponseExceptionType(
                value = ResourceModifiedException.class,
                code = {409})
        @UnexpectedResponseExceptionType(HttpResponseException.class)
        Mono<Response<BinaryData>> listProvidersNext(
                @PathParam(value = "nextLink", encoded = true) String nextLink,
                @HostParam("endpoint") String endpoint,
                @HeaderParam("Accept") String accept,
                RequestOptions requestOptions,
                Context context);

        @Get("{nextLink}")
        @ExpectedResponses({200})
        @UnexpectedResponseExceptionType(
                value = ClientAuthenticationException.class,
                code = {401})
        @UnexpectedResponseExceptionType(
                value = ResourceNotFoundException.class,
                code = {404})
        @UnexpectedResponseExceptionType(
                value = ResourceModifiedException.class,
                code = {409})
        @UnexpectedResponseExceptionType(HttpResponseException.class)
        Mono<Response<BinaryData>> listNamesNext(
                @PathParam(value = "nextLink", encoded = true) String nextLink,
                @HostParam("endpoint") String endpoint,
                @HeaderParam("Accept") String accept,
                RequestOptions requestOptions,
                Context context);

        @Get("{nextLink}")
        @ExpectedResponses({200})
        @UnexpectedResponseExceptionType(
                value = ClientAuthenticationException.class,
                code = {401})
        @UnexpectedResponseExceptionType(
                value = ResourceNotFoundException.class,
                code = {404})
        @UnexpectedResponseExceptionType(
                value = ResourceModifiedException.class,
                code = {409})
        @UnexpectedResponseExceptionType(HttpResponseException.class)
        Mono<Response<BinaryData>> listVersionsNext(
                @PathParam(value = "nextLink", encoded = true) String nextLink,
                @HostParam("endpoint") String endpoint,
                @HeaderParam("Accept") String accept,
                RequestOptions requestOptions,
                Context context);

        @Get("{nextLink}")
        @ExpectedResponses({200})
        @UnexpectedResponseExceptionType(
                value = ClientAuthenticationException.class,
                code = {401})
        @UnexpectedResponseExceptionType(
                value = ResourceNotFoundException.class,
                code = {404})
        @UnexpectedResponseExceptionType(
                value = ResourceModifiedException.class,
                code = {409})
        @UnexpectedResponseExceptionType(HttpResponseException.class)
        Mono<Response<BinaryData>> listFilesNext(
                @PathParam(value = "nextLink", encoded = true) String nextLink,
                @HostParam("endpoint") String endpoint,
                @HeaderParam("Accept") String accept,
                RequestOptions requestOptions,
                Context context);

        @Get("{nextLink}")
        @ExpectedResponses({200})
        @UnexpectedResponseExceptionType(
                value = ClientAuthenticationException.class,
                code = {401})
        @UnexpectedResponseExceptionType(
                value = ResourceNotFoundException.class,
                code = {404})
        @UnexpectedResponseExceptionType(
                value = ResourceModifiedException.class,
                code = {409})
        @UnexpectedResponseExceptionType(HttpResponseException.class)
        Mono<Response<BinaryData>> listOperationStatusesNext(
                @PathParam(value = "nextLink", encoded = true) String nextLink,
                @HostParam("endpoint") String endpoint,
                @HeaderParam("Accept") String accept,
                RequestOptions requestOptions,
                Context context);
    }

    /**
     * Get a list of all updates that have been imported to Device Update for IoT Hub.
     *
     * <p><strong>Query Parameters</strong>
     *
     * <table border="1">
     *     <caption>Query Parameters</caption>
     *     <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>
     *     <tr><td>search</td><td>String</td><td>No</td><td>Request updates matching a free-text search expression.</td></tr>
     *     <tr><td>filter</td><td>String</td><td>No</td><td>Optional to filter updates by isDeployable property.</td></tr>
     * </table>
     *
     * You can add these to a request with {@link RequestOptions#addQueryParam}
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *          (Required){
     *             updateId (Required): {
     *                 provider: String (Required)
     *                 name: String (Required)
     *                 version: String (Required)
     *             }
     *             description: String (Optional)
     *             friendlyName: String (Optional)
     *             isDeployable: Boolean (Optional)
     *             updateType: String (Optional)
     *             installedCriteria: String (Optional)
     *             compatibility (Required): [
     *                  (Required){
     *                     String: String (Required)
     *                 }
     *             ]
     *             instructions (Optional): {
     *                 steps (Required): [
     *                      (Required){
     *                         type: String(Inline/Reference) (Optional)
     *                         description: String (Optional)
     *                         handler: String (Optional)
     *                         handlerProperties: Object (Optional)
     *                         files (Optional): [
     *                             String (Optional)
     *                         ]
     *                         updateId (Optional): (recursive schema, see updateId above)
     *                     }
     *                 ]
     *             }
     *             referencedBy (Optional): [
     *                 (recursive schema, see above)
     *             ]
     *             scanResult: String (Optional)
     *             manifestVersion: String (Required)
     *             importedDateTime: OffsetDateTime (Required)
     *             createdDateTime: OffsetDateTime (Required)
     *             etag: String (Optional)
     *         }
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @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 a list of all updates that have been imported to Device Update for IoT Hub along with {@link
     *     PagedResponse} on successful completion of {@link Mono}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<PagedResponse<BinaryData>> listUpdatesSinglePageAsync(RequestOptions requestOptions) {
        final String accept = "application/json";
        return FluxUtil.withContext(
                        context ->
                                service.listUpdates(
                                        this.client.getEndpoint(),
                                        this.client.getInstanceId(),
                                        this.client.getServiceVersion().getVersion(),
                                        accept,
                                        requestOptions,
                                        context))
                .map(
                        res ->
                                new PagedResponseBase<>(
                                        res.getRequest(),
                                        res.getStatusCode(),
                                        res.getHeaders(),
                                        getValues(res.getValue(), "value"),
                                        getNextLink(res.getValue(), "nextLink"),
                                        null));
    }

    /**
     * Get a list of all updates that have been imported to Device Update for IoT Hub.
     *
     * <p><strong>Query Parameters</strong>
     *
     * <table border="1">
     *     <caption>Query Parameters</caption>
     *     <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>
     *     <tr><td>search</td><td>String</td><td>No</td><td>Request updates matching a free-text search expression.</td></tr>
     *     <tr><td>filter</td><td>String</td><td>No</td><td>Optional to filter updates by isDeployable property.</td></tr>
     * </table>
     *
     * You can add these to a request with {@link RequestOptions#addQueryParam}
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *          (Required){
     *             updateId (Required): {
     *                 provider: String (Required)
     *                 name: String (Required)
     *                 version: String (Required)
     *             }
     *             description: String (Optional)
     *             friendlyName: String (Optional)
     *             isDeployable: Boolean (Optional)
     *             updateType: String (Optional)
     *             installedCriteria: String (Optional)
     *             compatibility (Required): [
     *                  (Required){
     *                     String: String (Required)
     *                 }
     *             ]
     *             instructions (Optional): {
     *                 steps (Required): [
     *                      (Required){
     *                         type: String(Inline/Reference) (Optional)
     *                         description: String (Optional)
     *                         handler: String (Optional)
     *                         handlerProperties: Object (Optional)
     *                         files (Optional): [
     *                             String (Optional)
     *                         ]
     *                         updateId (Optional): (recursive schema, see updateId above)
     *                     }
     *                 ]
     *             }
     *             referencedBy (Optional): [
     *                 (recursive schema, see above)
     *             ]
     *             scanResult: String (Optional)
     *             manifestVersion: String (Required)
     *             importedDateTime: OffsetDateTime (Required)
     *             createdDateTime: OffsetDateTime (Required)
     *             etag: String (Optional)
     *         }
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @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 a list of all updates that have been imported to Device Update for IoT Hub as paginated response with
     *     {@link PagedFlux}.
     */
    @ServiceMethod(returns = ReturnType.COLLECTION)
    public PagedFlux<BinaryData> listUpdatesAsync(RequestOptions requestOptions) {
        RequestOptions requestOptionsForNextPage = new RequestOptions();
        requestOptionsForNextPage.setContext(
                requestOptions != null && requestOptions.getContext() != null
                        ? requestOptions.getContext()
                        : Context.NONE);
        return new PagedFlux<>(
                () -> listUpdatesSinglePageAsync(requestOptions),
                nextLink -> listUpdatesNextSinglePageAsync(nextLink, requestOptionsForNextPage));
    }

    /**
     * Get a list of all updates that have been imported to Device Update for IoT Hub.
     *
     * <p><strong>Query Parameters</strong>
     *
     * <table border="1">
     *     <caption>Query Parameters</caption>
     *     <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>
     *     <tr><td>search</td><td>String</td><td>No</td><td>Request updates matching a free-text search expression.</td></tr>
     *     <tr><td>filter</td><td>String</td><td>No</td><td>Optional to filter updates by isDeployable property.</td></tr>
     * </table>
     *
     * You can add these to a request with {@link RequestOptions#addQueryParam}
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *          (Required){
     *             updateId (Required): {
     *                 provider: String (Required)
     *                 name: String (Required)
     *                 version: String (Required)
     *             }
     *             description: String (Optional)
     *             friendlyName: String (Optional)
     *             isDeployable: Boolean (Optional)
     *             updateType: String (Optional)
     *             installedCriteria: String (Optional)
     *             compatibility (Required): [
     *                  (Required){
     *                     String: String (Required)
     *                 }
     *             ]
     *             instructions (Optional): {
     *                 steps (Required): [
     *                      (Required){
     *                         type: String(Inline/Reference) (Optional)
     *                         description: String (Optional)
     *                         handler: String (Optional)
     *                         handlerProperties: Object (Optional)
     *                         files (Optional): [
     *                             String (Optional)
     *                         ]
     *                         updateId (Optional): (recursive schema, see updateId above)
     *                     }
     *                 ]
     *             }
     *             referencedBy (Optional): [
     *                 (recursive schema, see above)
     *             ]
     *             scanResult: String (Optional)
     *             manifestVersion: String (Required)
     *             importedDateTime: OffsetDateTime (Required)
     *             createdDateTime: OffsetDateTime (Required)
     *             etag: String (Optional)
     *         }
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @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 a list of all updates that have been imported to Device Update for IoT Hub as paginated response with
     *     {@link PagedIterable}.
     */
    @ServiceMethod(returns = ReturnType.COLLECTION)
    public PagedIterable<BinaryData> listUpdates(RequestOptions requestOptions) {
        return new PagedIterable<>(listUpdatesAsync(requestOptions));
    }

    /**
     * Import new update version. This is a long-running-operation; use Operation-Location response header value to
     * check for operation status.
     *
     * <p><strong>Request Body Schema</strong>
     *
     * <pre>{@code
     * [
     *      (Required){
     *         importManifest (Required): {
     *             url: String (Required)
     *             sizeInBytes: long (Required)
     *             hashes (Required): {
     *                 String: String (Required)
     *             }
     *         }
     *         friendlyName: String (Optional)
     *         files (Optional): [
     *              (Optional){
     *                 filename: String (Required)
     *                 url: String (Required)
     *             }
     *         ]
     *     }
     * ]
     * }</pre>
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     updateId (Required): {
     *         provider: String (Required)
     *         name: String (Required)
     *         version: String (Required)
     *     }
     *     description: String (Optional)
     *     friendlyName: String (Optional)
     *     isDeployable: Boolean (Optional)
     *     updateType: String (Optional)
     *     installedCriteria: String (Optional)
     *     compatibility (Required): [
     *          (Required){
     *             String: String (Required)
     *         }
     *     ]
     *     instructions (Optional): {
     *         steps (Required): [
     *              (Required){
     *                 type: String(Inline/Reference) (Optional)
     *                 description: String (Optional)
     *                 handler: String (Optional)
     *                 handlerProperties: Object (Optional)
     *                 files (Optional): [
     *                     String (Optional)
     *                 ]
     *                 updateId (Optional): (recursive schema, see updateId above)
     *             }
     *         ]
     *     }
     *     referencedBy (Optional): [
     *         (recursive schema, see above)
     *     ]
     *     scanResult: String (Optional)
     *     manifestVersion: String (Required)
     *     importedDateTime: OffsetDateTime (Required)
     *     createdDateTime: OffsetDateTime (Required)
     *     etag: String (Optional)
     * }
     * }</pre>
     *
     * @param updateToImport The update to be imported (see schema
     *     https://json.schemastore.org/azure-deviceupdate-import-manifest-5.0.json for details).
     * @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 update metadata along with {@link Response} on successful completion of {@link Mono}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    private Mono<Response<BinaryData>> importUpdateWithResponseAsync(
            BinaryData updateToImport, RequestOptions requestOptions) {
        final String accept = "application/json";
        return FluxUtil.withContext(
                context ->
                        service.importUpdate(
                                this.client.getEndpoint(),
                                this.client.getInstanceId(),
                                this.client.getServiceVersion().getVersion(),
                                updateToImport,
                                accept,
                                requestOptions,
                                context));
    }

    /**
     * Import new update version. This is a long-running-operation; use Operation-Location response header value to
     * check for operation status.
     *
     * <p><strong>Request Body Schema</strong>
     *
     * <pre>{@code
     * [
     *      (Required){
     *         importManifest (Required): {
     *             url: String (Required)
     *             sizeInBytes: long (Required)
     *             hashes (Required): {
     *                 String: String (Required)
     *             }
     *         }
     *         friendlyName: String (Optional)
     *         files (Optional): [
     *              (Optional){
     *                 filename: String (Required)
     *                 url: String (Required)
     *             }
     *         ]
     *     }
     * ]
     * }</pre>
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     updateId (Required): {
     *         provider: String (Required)
     *         name: String (Required)
     *         version: String (Required)
     *     }
     *     description: String (Optional)
     *     friendlyName: String (Optional)
     *     isDeployable: Boolean (Optional)
     *     updateType: String (Optional)
     *     installedCriteria: String (Optional)
     *     compatibility (Required): [
     *          (Required){
     *             String: String (Required)
     *         }
     *     ]
     *     instructions (Optional): {
     *         steps (Required): [
     *              (Required){
     *                 type: String(Inline/Reference) (Optional)
     *                 description: String (Optional)
     *                 handler: String (Optional)
     *                 handlerProperties: Object (Optional)
     *                 files (Optional): [
     *                     String (Optional)
     *                 ]
     *                 updateId (Optional): (recursive schema, see updateId above)
     *             }
     *         ]
     *     }
     *     referencedBy (Optional): [
     *         (recursive schema, see above)
     *     ]
     *     scanResult: String (Optional)
     *     manifestVersion: String (Required)
     *     importedDateTime: OffsetDateTime (Required)
     *     createdDateTime: OffsetDateTime (Required)
     *     etag: String (Optional)
     * }
     * }</pre>
     *
     * @param updateToImport The update to be imported (see schema
     *     https://json.schemastore.org/azure-deviceupdate-import-manifest-5.0.json for details).
     * @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 {@link PollerFlux} for polling of update metadata.
     */
    @ServiceMethod(returns = ReturnType.LONG_RUNNING_OPERATION)
    public PollerFlux<BinaryData, BinaryData> beginImportUpdateAsync(
            BinaryData updateToImport, RequestOptions requestOptions) {
        return PollerFlux.create(
                Duration.ofSeconds(1),
                () -> this.importUpdateWithResponseAsync(updateToImport, requestOptions),
                new OperationResourcePollingStrategyWithEndpoint<>(
                        this.client.getHttpPipeline(),
                        "https://" + this.client.getEndpoint(),
                        null,
                        null,
                        requestOptions != null && requestOptions.getContext() != null
                                ? requestOptions.getContext()
                                : Context.NONE),
                TypeReference.createInstance(BinaryData.class),
                TypeReference.createInstance(BinaryData.class));
    }

    /**
     * Import new update version. This is a long-running-operation; use Operation-Location response header value to
     * check for operation status.
     *
     * <p><strong>Request Body Schema</strong>
     *
     * <pre>{@code
     * [
     *      (Required){
     *         importManifest (Required): {
     *             url: String (Required)
     *             sizeInBytes: long (Required)
     *             hashes (Required): {
     *                 String: String (Required)
     *             }
     *         }
     *         friendlyName: String (Optional)
     *         files (Optional): [
     *              (Optional){
     *                 filename: String (Required)
     *                 url: String (Required)
     *             }
     *         ]
     *     }
     * ]
     * }</pre>
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     updateId (Required): {
     *         provider: String (Required)
     *         name: String (Required)
     *         version: String (Required)
     *     }
     *     description: String (Optional)
     *     friendlyName: String (Optional)
     *     isDeployable: Boolean (Optional)
     *     updateType: String (Optional)
     *     installedCriteria: String (Optional)
     *     compatibility (Required): [
     *          (Required){
     *             String: String (Required)
     *         }
     *     ]
     *     instructions (Optional): {
     *         steps (Required): [
     *              (Required){
     *                 type: String(Inline/Reference) (Optional)
     *                 description: String (Optional)
     *                 handler: String (Optional)
     *                 handlerProperties: Object (Optional)
     *                 files (Optional): [
     *                     String (Optional)
     *                 ]
     *                 updateId (Optional): (recursive schema, see updateId above)
     *             }
     *         ]
     *     }
     *     referencedBy (Optional): [
     *         (recursive schema, see above)
     *     ]
     *     scanResult: String (Optional)
     *     manifestVersion: String (Required)
     *     importedDateTime: OffsetDateTime (Required)
     *     createdDateTime: OffsetDateTime (Required)
     *     etag: String (Optional)
     * }
     * }</pre>
     *
     * @param updateToImport The update to be imported (see schema
     *     https://json.schemastore.org/azure-deviceupdate-import-manifest-5.0.json for details).
     * @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 {@link SyncPoller} for polling of update metadata.
     */
    @ServiceMethod(returns = ReturnType.LONG_RUNNING_OPERATION)
    public SyncPoller<BinaryData, BinaryData> beginImportUpdate(
            BinaryData updateToImport, RequestOptions requestOptions) {
        return this.beginImportUpdateAsync(updateToImport, requestOptions).getSyncPoller();
    }

    /**
     * Get a specific update version.
     *
     * <p><strong>Header Parameters</strong>
     *
     * <table border="1">
     *     <caption>Header Parameters</caption>
     *     <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>
     *     <tr><td>If-None-Match</td><td>String</td><td>No</td><td>Defines the If-None-Match condition. The operation will be performed only if the ETag on the server does not match this value.</td></tr>
     * </table>
     *
     * You can add these to a request with {@link RequestOptions#addHeader}
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     updateId (Required): {
     *         provider: String (Required)
     *         name: String (Required)
     *         version: String (Required)
     *     }
     *     description: String (Optional)
     *     friendlyName: String (Optional)
     *     isDeployable: Boolean (Optional)
     *     updateType: String (Optional)
     *     installedCriteria: String (Optional)
     *     compatibility (Required): [
     *          (Required){
     *             String: String (Required)
     *         }
     *     ]
     *     instructions (Optional): {
     *         steps (Required): [
     *              (Required){
     *                 type: String(Inline/Reference) (Optional)
     *                 description: String (Optional)
     *                 handler: String (Optional)
     *                 handlerProperties: Object (Optional)
     *                 files (Optional): [
     *                     String (Optional)
     *                 ]
     *                 updateId (Optional): (recursive schema, see updateId above)
     *             }
     *         ]
     *     }
     *     referencedBy (Optional): [
     *         (recursive schema, see above)
     *     ]
     *     scanResult: String (Optional)
     *     manifestVersion: String (Required)
     *     importedDateTime: OffsetDateTime (Required)
     *     createdDateTime: OffsetDateTime (Required)
     *     etag: String (Optional)
     * }
     * }</pre>
     *
     * @param provider Update provider.
     * @param name Update name.
     * @param version Update version.
     * @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 a specific update version along with {@link Response} on successful completion of {@link Mono}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<Response<BinaryData>> getUpdateWithResponseAsync(
            String provider, String name, String version, RequestOptions requestOptions) {
        final String accept = "application/json";
        return FluxUtil.withContext(
                context ->
                        service.getUpdate(
                                this.client.getEndpoint(),
                                this.client.getInstanceId(),
                                provider,
                                name,
                                version,
                                this.client.getServiceVersion().getVersion(),
                                accept,
                                requestOptions,
                                context));
    }

    /**
     * Get a specific update version.
     *
     * <p><strong>Header Parameters</strong>
     *
     * <table border="1">
     *     <caption>Header Parameters</caption>
     *     <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>
     *     <tr><td>If-None-Match</td><td>String</td><td>No</td><td>Defines the If-None-Match condition. The operation will be performed only if the ETag on the server does not match this value.</td></tr>
     * </table>
     *
     * You can add these to a request with {@link RequestOptions#addHeader}
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     updateId (Required): {
     *         provider: String (Required)
     *         name: String (Required)
     *         version: String (Required)
     *     }
     *     description: String (Optional)
     *     friendlyName: String (Optional)
     *     isDeployable: Boolean (Optional)
     *     updateType: String (Optional)
     *     installedCriteria: String (Optional)
     *     compatibility (Required): [
     *          (Required){
     *             String: String (Required)
     *         }
     *     ]
     *     instructions (Optional): {
     *         steps (Required): [
     *              (Required){
     *                 type: String(Inline/Reference) (Optional)
     *                 description: String (Optional)
     *                 handler: String (Optional)
     *                 handlerProperties: Object (Optional)
     *                 files (Optional): [
     *                     String (Optional)
     *                 ]
     *                 updateId (Optional): (recursive schema, see updateId above)
     *             }
     *         ]
     *     }
     *     referencedBy (Optional): [
     *         (recursive schema, see above)
     *     ]
     *     scanResult: String (Optional)
     *     manifestVersion: String (Required)
     *     importedDateTime: OffsetDateTime (Required)
     *     createdDateTime: OffsetDateTime (Required)
     *     etag: String (Optional)
     * }
     * }</pre>
     *
     * @param provider Update provider.
     * @param name Update name.
     * @param version Update version.
     * @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 a specific update version along with {@link Response}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Response<BinaryData> getUpdateWithResponse(
            String provider, String name, String version, RequestOptions requestOptions) {
        return getUpdateWithResponseAsync(provider, name, version, requestOptions).block();
    }

    /**
     * Delete a specific update version. This is a long-running-operation; use Operation-Location response header value
     * to check for operation status.
     *
     * @param provider Update provider.
     * @param name Update name.
     * @param version Update version.
     * @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 {@link Response} on successful completion of {@link Mono}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    private Mono<Response<Void>> deleteUpdateWithResponseAsync(
            String provider, String name, String version, RequestOptions requestOptions) {
        final String accept = "application/json";
        return FluxUtil.withContext(
                context ->
                        service.deleteUpdate(
                                this.client.getEndpoint(),
                                this.client.getInstanceId(),
                                provider,
                                name,
                                version,
                                this.client.getServiceVersion().getVersion(),
                                accept,
                                requestOptions,
                                context));
    }

    /**
     * Delete a specific update version. This is a long-running-operation; use Operation-Location response header value
     * to check for operation status.
     *
     * @param provider Update provider.
     * @param name Update name.
     * @param version Update version.
     * @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 {@link PollerFlux} for polling of long-running operation.
     */
    @ServiceMethod(returns = ReturnType.LONG_RUNNING_OPERATION)
    public PollerFlux<BinaryData, BinaryData> beginDeleteUpdateAsync(
            String provider, String name, String version, RequestOptions requestOptions) {
        return PollerFlux.create(
                Duration.ofSeconds(1),
                () -> this.deleteUpdateWithResponseAsync(provider, name, version, requestOptions),
                new OperationResourcePollingStrategyWithEndpoint<>(
                        this.client.getHttpPipeline(),
                        "https://" + this.client.getEndpoint(),
                        null,
                        null,
                        requestOptions != null && requestOptions.getContext() != null
                                ? requestOptions.getContext()
                                : Context.NONE),
                TypeReference.createInstance(BinaryData.class),
                TypeReference.createInstance(BinaryData.class));
    }

    /**
     * Delete a specific update version. This is a long-running-operation; use Operation-Location response header value
     * to check for operation status.
     *
     * @param provider Update provider.
     * @param name Update name.
     * @param version Update version.
     * @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 {@link SyncPoller} for polling of long-running operation.
     */
    @ServiceMethod(returns = ReturnType.LONG_RUNNING_OPERATION)
    public SyncPoller<BinaryData, BinaryData> beginDeleteUpdate(
            String provider, String name, String version, RequestOptions requestOptions) {
        return this.beginDeleteUpdateAsync(provider, name, version, requestOptions).getSyncPoller();
    }

    /**
     * Get a list of all update providers that have been imported to Device Update for IoT Hub.
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *         String (Required)
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @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 a list of all update providers that have been imported to Device Update for IoT Hub along with {@link
     *     PagedResponse} on successful completion of {@link Mono}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<PagedResponse<BinaryData>> listProvidersSinglePageAsync(RequestOptions requestOptions) {
        final String accept = "application/json";
        return FluxUtil.withContext(
                        context ->
                                service.listProviders(
                                        this.client.getEndpoint(),
                                        this.client.getInstanceId(),
                                        this.client.getServiceVersion().getVersion(),
                                        accept,
                                        requestOptions,
                                        context))
                .map(
                        res ->
                                new PagedResponseBase<>(
                                        res.getRequest(),
                                        res.getStatusCode(),
                                        res.getHeaders(),
                                        getValues(res.getValue(), "value"),
                                        getNextLink(res.getValue(), "nextLink"),
                                        null));
    }

    /**
     * Get a list of all update providers that have been imported to Device Update for IoT Hub.
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *         String (Required)
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @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 a list of all update providers that have been imported to Device Update for IoT Hub as paginated response
     *     with {@link PagedFlux}.
     */
    @ServiceMethod(returns = ReturnType.COLLECTION)
    public PagedFlux<BinaryData> listProvidersAsync(RequestOptions requestOptions) {
        RequestOptions requestOptionsForNextPage = new RequestOptions();
        requestOptionsForNextPage.setContext(
                requestOptions != null && requestOptions.getContext() != null
                        ? requestOptions.getContext()
                        : Context.NONE);
        return new PagedFlux<>(
                () -> listProvidersSinglePageAsync(requestOptions),
                nextLink -> listProvidersNextSinglePageAsync(nextLink, requestOptionsForNextPage));
    }

    /**
     * Get a list of all update providers that have been imported to Device Update for IoT Hub.
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *         String (Required)
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @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 a list of all update providers that have been imported to Device Update for IoT Hub as paginated response
     *     with {@link PagedIterable}.
     */
    @ServiceMethod(returns = ReturnType.COLLECTION)
    public PagedIterable<BinaryData> listProviders(RequestOptions requestOptions) {
        return new PagedIterable<>(listProvidersAsync(requestOptions));
    }

    /**
     * Get a list of all update names that match the specified provider.
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *         String (Required)
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @param provider Update provider.
     * @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 a list of all update names that match the specified provider along with {@link PagedResponse} on
     *     successful completion of {@link Mono}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<PagedResponse<BinaryData>> listNamesSinglePageAsync(String provider, RequestOptions requestOptions) {
        final String accept = "application/json";
        return FluxUtil.withContext(
                        context ->
                                service.listNames(
                                        this.client.getEndpoint(),
                                        this.client.getInstanceId(),
                                        provider,
                                        this.client.getServiceVersion().getVersion(),
                                        accept,
                                        requestOptions,
                                        context))
                .map(
                        res ->
                                new PagedResponseBase<>(
                                        res.getRequest(),
                                        res.getStatusCode(),
                                        res.getHeaders(),
                                        getValues(res.getValue(), "value"),
                                        getNextLink(res.getValue(), "nextLink"),
                                        null));
    }

    /**
     * Get a list of all update names that match the specified provider.
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *         String (Required)
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @param provider Update provider.
     * @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 a list of all update names that match the specified provider as paginated response with {@link
     *     PagedFlux}.
     */
    @ServiceMethod(returns = ReturnType.COLLECTION)
    public PagedFlux<BinaryData> listNamesAsync(String provider, RequestOptions requestOptions) {
        RequestOptions requestOptionsForNextPage = new RequestOptions();
        requestOptionsForNextPage.setContext(
                requestOptions != null && requestOptions.getContext() != null
                        ? requestOptions.getContext()
                        : Context.NONE);
        return new PagedFlux<>(
                () -> listNamesSinglePageAsync(provider, requestOptions),
                nextLink -> listNamesNextSinglePageAsync(nextLink, requestOptionsForNextPage));
    }

    /**
     * Get a list of all update names that match the specified provider.
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *         String (Required)
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @param provider Update provider.
     * @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 a list of all update names that match the specified provider as paginated response with {@link
     *     PagedIterable}.
     */
    @ServiceMethod(returns = ReturnType.COLLECTION)
    public PagedIterable<BinaryData> listNames(String provider, RequestOptions requestOptions) {
        return new PagedIterable<>(listNamesAsync(provider, requestOptions));
    }

    /**
     * Get a list of all update versions that match the specified provider and name.
     *
     * <p><strong>Query Parameters</strong>
     *
     * <table border="1">
     *     <caption>Query Parameters</caption>
     *     <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>
     *     <tr><td>filter</td><td>String</td><td>No</td><td>Optional to filter updates by isDeployable property.</td></tr>
     * </table>
     *
     * You can add these to a request with {@link RequestOptions#addQueryParam}
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *         String (Required)
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @param provider Update provider.
     * @param name Update name.
     * @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 a list of all update versions that match the specified provider and name along with {@link PagedResponse}
     *     on successful completion of {@link Mono}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<PagedResponse<BinaryData>> listVersionsSinglePageAsync(
            String provider, String name, RequestOptions requestOptions) {
        final String accept = "application/json";
        return FluxUtil.withContext(
                        context ->
                                service.listVersions(
                                        this.client.getEndpoint(),
                                        this.client.getInstanceId(),
                                        provider,
                                        name,
                                        this.client.getServiceVersion().getVersion(),
                                        accept,
                                        requestOptions,
                                        context))
                .map(
                        res ->
                                new PagedResponseBase<>(
                                        res.getRequest(),
                                        res.getStatusCode(),
                                        res.getHeaders(),
                                        getValues(res.getValue(), "value"),
                                        getNextLink(res.getValue(), "nextLink"),
                                        null));
    }

    /**
     * Get a list of all update versions that match the specified provider and name.
     *
     * <p><strong>Query Parameters</strong>
     *
     * <table border="1">
     *     <caption>Query Parameters</caption>
     *     <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>
     *     <tr><td>filter</td><td>String</td><td>No</td><td>Optional to filter updates by isDeployable property.</td></tr>
     * </table>
     *
     * You can add these to a request with {@link RequestOptions#addQueryParam}
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *         String (Required)
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @param provider Update provider.
     * @param name Update name.
     * @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 a list of all update versions that match the specified provider and name as paginated response with
     *     {@link PagedFlux}.
     */
    @ServiceMethod(returns = ReturnType.COLLECTION)
    public PagedFlux<BinaryData> listVersionsAsync(String provider, String name, RequestOptions requestOptions) {
        RequestOptions requestOptionsForNextPage = new RequestOptions();
        requestOptionsForNextPage.setContext(
                requestOptions != null && requestOptions.getContext() != null
                        ? requestOptions.getContext()
                        : Context.NONE);
        return new PagedFlux<>(
                () -> listVersionsSinglePageAsync(provider, name, requestOptions),
                nextLink -> listVersionsNextSinglePageAsync(nextLink, requestOptionsForNextPage));
    }

    /**
     * Get a list of all update versions that match the specified provider and name.
     *
     * <p><strong>Query Parameters</strong>
     *
     * <table border="1">
     *     <caption>Query Parameters</caption>
     *     <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>
     *     <tr><td>filter</td><td>String</td><td>No</td><td>Optional to filter updates by isDeployable property.</td></tr>
     * </table>
     *
     * You can add these to a request with {@link RequestOptions#addQueryParam}
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *         String (Required)
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @param provider Update provider.
     * @param name Update name.
     * @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 a list of all update versions that match the specified provider and name as paginated response with
     *     {@link PagedIterable}.
     */
    @ServiceMethod(returns = ReturnType.COLLECTION)
    public PagedIterable<BinaryData> listVersions(String provider, String name, RequestOptions requestOptions) {
        return new PagedIterable<>(listVersionsAsync(provider, name, requestOptions));
    }

    /**
     * Get a list of all update file identifiers for the specified version.
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *         String (Required)
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @param provider Update provider.
     * @param name Update name.
     * @param version Update version.
     * @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 a list of all update file identifiers for the specified version along with {@link PagedResponse} on
     *     successful completion of {@link Mono}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<PagedResponse<BinaryData>> listFilesSinglePageAsync(
            String provider, String name, String version, RequestOptions requestOptions) {
        final String accept = "application/json";
        return FluxUtil.withContext(
                        context ->
                                service.listFiles(
                                        this.client.getEndpoint(),
                                        this.client.getInstanceId(),
                                        provider,
                                        name,
                                        version,
                                        this.client.getServiceVersion().getVersion(),
                                        accept,
                                        requestOptions,
                                        context))
                .map(
                        res ->
                                new PagedResponseBase<>(
                                        res.getRequest(),
                                        res.getStatusCode(),
                                        res.getHeaders(),
                                        getValues(res.getValue(), "value"),
                                        getNextLink(res.getValue(), "nextLink"),
                                        null));
    }

    /**
     * Get a list of all update file identifiers for the specified version.
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *         String (Required)
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @param provider Update provider.
     * @param name Update name.
     * @param version Update version.
     * @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 a list of all update file identifiers for the specified version as paginated response with {@link
     *     PagedFlux}.
     */
    @ServiceMethod(returns = ReturnType.COLLECTION)
    public PagedFlux<BinaryData> listFilesAsync(
            String provider, String name, String version, RequestOptions requestOptions) {
        RequestOptions requestOptionsForNextPage = new RequestOptions();
        requestOptionsForNextPage.setContext(
                requestOptions != null && requestOptions.getContext() != null
                        ? requestOptions.getContext()
                        : Context.NONE);
        return new PagedFlux<>(
                () -> listFilesSinglePageAsync(provider, name, version, requestOptions),
                nextLink -> listFilesNextSinglePageAsync(nextLink, requestOptionsForNextPage));
    }

    /**
     * Get a list of all update file identifiers for the specified version.
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *         String (Required)
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @param provider Update provider.
     * @param name Update name.
     * @param version Update version.
     * @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 a list of all update file identifiers for the specified version as paginated response with {@link
     *     PagedIterable}.
     */
    @ServiceMethod(returns = ReturnType.COLLECTION)
    public PagedIterable<BinaryData> listFiles(
            String provider, String name, String version, RequestOptions requestOptions) {
        return new PagedIterable<>(listFilesAsync(provider, name, version, requestOptions));
    }

    /**
     * Get a specific update file from the version.
     *
     * <p><strong>Header Parameters</strong>
     *
     * <table border="1">
     *     <caption>Header Parameters</caption>
     *     <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>
     *     <tr><td>If-None-Match</td><td>String</td><td>No</td><td>Defines the If-None-Match condition. The operation will be performed only if the ETag on the server does not match this value.</td></tr>
     * </table>
     *
     * You can add these to a request with {@link RequestOptions#addHeader}
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     fileName: String (Required)
     *     sizeInBytes: long (Required)
     *     hashes (Required): {
     *         String: String (Required)
     *     }
     *     mimeType: String (Optional)
     *     scanResult: String (Optional)
     *     scanDetails: String (Optional)
     *     properties (Optional): {
     *         String: String (Optional)
     *     }
     *     fileId: String (Required)
     *     relatedFiles (Optional): [
     *          (Optional){
     *             fileName: String (Required)
     *             sizeInBytes: long (Required)
     *             hashes (Required): {
     *                 String: String (Required)
     *             }
     *             mimeType: String (Optional)
     *             scanResult: String (Optional)
     *             scanDetails: String (Optional)
     *             properties (Optional): {
     *                 String: String (Optional)
     *             }
     *         }
     *     ]
     *     downloadHandler (Optional): {
     *         id: String (Required)
     *     }
     *     etag: String (Optional)
     * }
     * }</pre>
     *
     * @param provider Update provider.
     * @param name Update name.
     * @param version Update version.
     * @param fileId File identifier.
     * @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 a specific update file from the version along with {@link Response} on successful completion of {@link
     *     Mono}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<Response<BinaryData>> getFileWithResponseAsync(
            String provider, String name, String version, String fileId, RequestOptions requestOptions) {
        final String accept = "application/json";
        return FluxUtil.withContext(
                context ->
                        service.getFile(
                                this.client.getEndpoint(),
                                this.client.getInstanceId(),
                                provider,
                                name,
                                version,
                                fileId,
                                this.client.getServiceVersion().getVersion(),
                                accept,
                                requestOptions,
                                context));
    }

    /**
     * Get a specific update file from the version.
     *
     * <p><strong>Header Parameters</strong>
     *
     * <table border="1">
     *     <caption>Header Parameters</caption>
     *     <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>
     *     <tr><td>If-None-Match</td><td>String</td><td>No</td><td>Defines the If-None-Match condition. The operation will be performed only if the ETag on the server does not match this value.</td></tr>
     * </table>
     *
     * You can add these to a request with {@link RequestOptions#addHeader}
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     fileName: String (Required)
     *     sizeInBytes: long (Required)
     *     hashes (Required): {
     *         String: String (Required)
     *     }
     *     mimeType: String (Optional)
     *     scanResult: String (Optional)
     *     scanDetails: String (Optional)
     *     properties (Optional): {
     *         String: String (Optional)
     *     }
     *     fileId: String (Required)
     *     relatedFiles (Optional): [
     *          (Optional){
     *             fileName: String (Required)
     *             sizeInBytes: long (Required)
     *             hashes (Required): {
     *                 String: String (Required)
     *             }
     *             mimeType: String (Optional)
     *             scanResult: String (Optional)
     *             scanDetails: String (Optional)
     *             properties (Optional): {
     *                 String: String (Optional)
     *             }
     *         }
     *     ]
     *     downloadHandler (Optional): {
     *         id: String (Required)
     *     }
     *     etag: String (Optional)
     * }
     * }</pre>
     *
     * @param provider Update provider.
     * @param name Update name.
     * @param version Update version.
     * @param fileId File identifier.
     * @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 a specific update file from the version along with {@link Response}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Response<BinaryData> getFileWithResponse(
            String provider, String name, String version, String fileId, RequestOptions requestOptions) {
        return getFileWithResponseAsync(provider, name, version, fileId, requestOptions).block();
    }

    /**
     * Get a list of all import update operations. Completed operations are kept for 7 days before auto-deleted. Delete
     * operations are not returned by this API version.
     *
     * <p><strong>Query Parameters</strong>
     *
     * <table border="1">
     *     <caption>Query Parameters</caption>
     *     <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>
     *     <tr><td>filter</td><td>String</td><td>No</td><td>Optional to filter operations by status property. Only one specific filter is supported: "status eq 'NotStarted' or status eq 'Running'"</td></tr>
     *     <tr><td>top</td><td>Integer</td><td>No</td><td>Specifies a non-negative integer n that limits the number of items returned from a collection. The service returns the number of available items up to but not greater than the specified value n.</td></tr>
     * </table>
     *
     * You can add these to a request with {@link RequestOptions#addQueryParam}
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *          (Required){
     *             operationId: String (Required)
     *             status: String(NotStarted/Running/Succeeded/Failed) (Required)
     *             update (Optional): {
     *                 updateId (Required): {
     *                     provider: String (Required)
     *                     name: String (Required)
     *                     version: String (Required)
     *                 }
     *                 description: String (Optional)
     *                 friendlyName: String (Optional)
     *             }
     *             resourceLocation: String (Optional)
     *             error (Optional): {
     *                 code: String (Required)
     *                 message: String (Required)
     *                 target: String (Optional)
     *                 details (Optional): [
     *                     (recursive schema, see above)
     *                 ]
     *                 innererror (Optional): {
     *                     code: String (Required)
     *                     message: String (Optional)
     *                     errorDetail: String (Optional)
     *                     innerError (Optional): (recursive schema, see innerError above)
     *                 }
     *                 occurredDateTime: OffsetDateTime (Optional)
     *             }
     *             traceId: String (Optional)
     *             lastActionDateTime: OffsetDateTime (Required)
     *             createdDateTime: OffsetDateTime (Required)
     *             etag: String (Optional)
     *         }
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @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 a list of all import update operations along with {@link PagedResponse} on successful completion of
     *     {@link Mono}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<PagedResponse<BinaryData>> listOperationStatusesSinglePageAsync(RequestOptions requestOptions) {
        final String accept = "application/json";
        return FluxUtil.withContext(
                        context ->
                                service.listOperationStatuses(
                                        this.client.getEndpoint(),
                                        this.client.getInstanceId(),
                                        this.client.getServiceVersion().getVersion(),
                                        accept,
                                        requestOptions,
                                        context))
                .map(
                        res ->
                                new PagedResponseBase<>(
                                        res.getRequest(),
                                        res.getStatusCode(),
                                        res.getHeaders(),
                                        getValues(res.getValue(), "value"),
                                        getNextLink(res.getValue(), "nextLink"),
                                        null));
    }

    /**
     * Get a list of all import update operations. Completed operations are kept for 7 days before auto-deleted. Delete
     * operations are not returned by this API version.
     *
     * <p><strong>Query Parameters</strong>
     *
     * <table border="1">
     *     <caption>Query Parameters</caption>
     *     <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>
     *     <tr><td>filter</td><td>String</td><td>No</td><td>Optional to filter operations by status property. Only one specific filter is supported: "status eq 'NotStarted' or status eq 'Running'"</td></tr>
     *     <tr><td>top</td><td>Integer</td><td>No</td><td>Specifies a non-negative integer n that limits the number of items returned from a collection. The service returns the number of available items up to but not greater than the specified value n.</td></tr>
     * </table>
     *
     * You can add these to a request with {@link RequestOptions#addQueryParam}
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *          (Required){
     *             operationId: String (Required)
     *             status: String(NotStarted/Running/Succeeded/Failed) (Required)
     *             update (Optional): {
     *                 updateId (Required): {
     *                     provider: String (Required)
     *                     name: String (Required)
     *                     version: String (Required)
     *                 }
     *                 description: String (Optional)
     *                 friendlyName: String (Optional)
     *             }
     *             resourceLocation: String (Optional)
     *             error (Optional): {
     *                 code: String (Required)
     *                 message: String (Required)
     *                 target: String (Optional)
     *                 details (Optional): [
     *                     (recursive schema, see above)
     *                 ]
     *                 innererror (Optional): {
     *                     code: String (Required)
     *                     message: String (Optional)
     *                     errorDetail: String (Optional)
     *                     innerError (Optional): (recursive schema, see innerError above)
     *                 }
     *                 occurredDateTime: OffsetDateTime (Optional)
     *             }
     *             traceId: String (Optional)
     *             lastActionDateTime: OffsetDateTime (Required)
     *             createdDateTime: OffsetDateTime (Required)
     *             etag: String (Optional)
     *         }
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @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 a list of all import update operations as paginated response with {@link PagedFlux}.
     */
    @ServiceMethod(returns = ReturnType.COLLECTION)
    public PagedFlux<BinaryData> listOperationStatusesAsync(RequestOptions requestOptions) {
        RequestOptions requestOptionsForNextPage = new RequestOptions();
        requestOptionsForNextPage.setContext(
                requestOptions != null && requestOptions.getContext() != null
                        ? requestOptions.getContext()
                        : Context.NONE);
        return new PagedFlux<>(
                () -> listOperationStatusesSinglePageAsync(requestOptions),
                nextLink -> listOperationStatusesNextSinglePageAsync(nextLink, requestOptionsForNextPage));
    }

    /**
     * Get a list of all import update operations. Completed operations are kept for 7 days before auto-deleted. Delete
     * operations are not returned by this API version.
     *
     * <p><strong>Query Parameters</strong>
     *
     * <table border="1">
     *     <caption>Query Parameters</caption>
     *     <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>
     *     <tr><td>filter</td><td>String</td><td>No</td><td>Optional to filter operations by status property. Only one specific filter is supported: "status eq 'NotStarted' or status eq 'Running'"</td></tr>
     *     <tr><td>top</td><td>Integer</td><td>No</td><td>Specifies a non-negative integer n that limits the number of items returned from a collection. The service returns the number of available items up to but not greater than the specified value n.</td></tr>
     * </table>
     *
     * You can add these to a request with {@link RequestOptions#addQueryParam}
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *          (Required){
     *             operationId: String (Required)
     *             status: String(NotStarted/Running/Succeeded/Failed) (Required)
     *             update (Optional): {
     *                 updateId (Required): {
     *                     provider: String (Required)
     *                     name: String (Required)
     *                     version: String (Required)
     *                 }
     *                 description: String (Optional)
     *                 friendlyName: String (Optional)
     *             }
     *             resourceLocation: String (Optional)
     *             error (Optional): {
     *                 code: String (Required)
     *                 message: String (Required)
     *                 target: String (Optional)
     *                 details (Optional): [
     *                     (recursive schema, see above)
     *                 ]
     *                 innererror (Optional): {
     *                     code: String (Required)
     *                     message: String (Optional)
     *                     errorDetail: String (Optional)
     *                     innerError (Optional): (recursive schema, see innerError above)
     *                 }
     *                 occurredDateTime: OffsetDateTime (Optional)
     *             }
     *             traceId: String (Optional)
     *             lastActionDateTime: OffsetDateTime (Required)
     *             createdDateTime: OffsetDateTime (Required)
     *             etag: String (Optional)
     *         }
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @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 a list of all import update operations as paginated response with {@link PagedIterable}.
     */
    @ServiceMethod(returns = ReturnType.COLLECTION)
    public PagedIterable<BinaryData> listOperationStatuses(RequestOptions requestOptions) {
        return new PagedIterable<>(listOperationStatusesAsync(requestOptions));
    }

    /**
     * Retrieve operation status.
     *
     * <p><strong>Header Parameters</strong>
     *
     * <table border="1">
     *     <caption>Header Parameters</caption>
     *     <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>
     *     <tr><td>If-None-Match</td><td>String</td><td>No</td><td>Defines the If-None-Match condition. The operation will be performed only if the ETag on the server does not match this value.</td></tr>
     * </table>
     *
     * You can add these to a request with {@link RequestOptions#addHeader}
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     operationId: String (Required)
     *     status: String(NotStarted/Running/Succeeded/Failed) (Required)
     *     update (Optional): {
     *         updateId (Required): {
     *             provider: String (Required)
     *             name: String (Required)
     *             version: String (Required)
     *         }
     *         description: String (Optional)
     *         friendlyName: String (Optional)
     *     }
     *     resourceLocation: String (Optional)
     *     error (Optional): {
     *         code: String (Required)
     *         message: String (Required)
     *         target: String (Optional)
     *         details (Optional): [
     *             (recursive schema, see above)
     *         ]
     *         innererror (Optional): {
     *             code: String (Required)
     *             message: String (Optional)
     *             errorDetail: String (Optional)
     *             innerError (Optional): (recursive schema, see innerError above)
     *         }
     *         occurredDateTime: OffsetDateTime (Optional)
     *     }
     *     traceId: String (Optional)
     *     lastActionDateTime: OffsetDateTime (Required)
     *     createdDateTime: OffsetDateTime (Required)
     *     etag: String (Optional)
     * }
     * }</pre>
     *
     * @param operationId Operation identifier.
     * @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 operation metadata along with {@link Response} on successful completion of {@link Mono}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<Response<BinaryData>> getOperationStatusWithResponseAsync(
            String operationId, RequestOptions requestOptions) {
        final String accept = "application/json";
        return FluxUtil.withContext(
                context ->
                        service.getOperationStatus(
                                this.client.getEndpoint(),
                                this.client.getInstanceId(),
                                operationId,
                                this.client.getServiceVersion().getVersion(),
                                accept,
                                requestOptions,
                                context));
    }

    /**
     * Retrieve operation status.
     *
     * <p><strong>Header Parameters</strong>
     *
     * <table border="1">
     *     <caption>Header Parameters</caption>
     *     <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>
     *     <tr><td>If-None-Match</td><td>String</td><td>No</td><td>Defines the If-None-Match condition. The operation will be performed only if the ETag on the server does not match this value.</td></tr>
     * </table>
     *
     * You can add these to a request with {@link RequestOptions#addHeader}
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     operationId: String (Required)
     *     status: String(NotStarted/Running/Succeeded/Failed) (Required)
     *     update (Optional): {
     *         updateId (Required): {
     *             provider: String (Required)
     *             name: String (Required)
     *             version: String (Required)
     *         }
     *         description: String (Optional)
     *         friendlyName: String (Optional)
     *     }
     *     resourceLocation: String (Optional)
     *     error (Optional): {
     *         code: String (Required)
     *         message: String (Required)
     *         target: String (Optional)
     *         details (Optional): [
     *             (recursive schema, see above)
     *         ]
     *         innererror (Optional): {
     *             code: String (Required)
     *             message: String (Optional)
     *             errorDetail: String (Optional)
     *             innerError (Optional): (recursive schema, see innerError above)
     *         }
     *         occurredDateTime: OffsetDateTime (Optional)
     *     }
     *     traceId: String (Optional)
     *     lastActionDateTime: OffsetDateTime (Required)
     *     createdDateTime: OffsetDateTime (Required)
     *     etag: String (Optional)
     * }
     * }</pre>
     *
     * @param operationId Operation identifier.
     * @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 operation metadata along with {@link Response}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Response<BinaryData> getOperationStatusWithResponse(String operationId, RequestOptions requestOptions) {
        return getOperationStatusWithResponseAsync(operationId, requestOptions).block();
    }

    /**
     * Get the next page of items.
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *          (Required){
     *             updateId (Required): {
     *                 provider: String (Required)
     *                 name: String (Required)
     *                 version: String (Required)
     *             }
     *             description: String (Optional)
     *             friendlyName: String (Optional)
     *             isDeployable: Boolean (Optional)
     *             updateType: String (Optional)
     *             installedCriteria: String (Optional)
     *             compatibility (Required): [
     *                  (Required){
     *                     String: String (Required)
     *                 }
     *             ]
     *             instructions (Optional): {
     *                 steps (Required): [
     *                      (Required){
     *                         type: String(Inline/Reference) (Optional)
     *                         description: String (Optional)
     *                         handler: String (Optional)
     *                         handlerProperties: Object (Optional)
     *                         files (Optional): [
     *                             String (Optional)
     *                         ]
     *                         updateId (Optional): (recursive schema, see updateId above)
     *                     }
     *                 ]
     *             }
     *             referencedBy (Optional): [
     *                 (recursive schema, see above)
     *             ]
     *             scanResult: String (Optional)
     *             manifestVersion: String (Required)
     *             importedDateTime: OffsetDateTime (Required)
     *             createdDateTime: OffsetDateTime (Required)
     *             etag: String (Optional)
     *         }
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @param nextLink The URL to get the next list of items
     *     <p>The nextLink 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 list of updates along with {@link PagedResponse} on successful completion of {@link Mono}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<PagedResponse<BinaryData>> listUpdatesNextSinglePageAsync(
            String nextLink, RequestOptions requestOptions) {
        final String accept = "application/json";
        return FluxUtil.withContext(
                        context ->
                                service.listUpdatesNext(
                                        nextLink, this.client.getEndpoint(), accept, requestOptions, context))
                .map(
                        res ->
                                new PagedResponseBase<>(
                                        res.getRequest(),
                                        res.getStatusCode(),
                                        res.getHeaders(),
                                        getValues(res.getValue(), "value"),
                                        getNextLink(res.getValue(), "nextLink"),
                                        null));
    }

    /**
     * Get the next page of items.
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *         String (Required)
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @param nextLink The URL to get the next list of items
     *     <p>The nextLink 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 list of strings with server paging support along with {@link PagedResponse} on successful completion
     *     of {@link Mono}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<PagedResponse<BinaryData>> listProvidersNextSinglePageAsync(
            String nextLink, RequestOptions requestOptions) {
        final String accept = "application/json";
        return FluxUtil.withContext(
                        context ->
                                service.listProvidersNext(
                                        nextLink, this.client.getEndpoint(), accept, requestOptions, context))
                .map(
                        res ->
                                new PagedResponseBase<>(
                                        res.getRequest(),
                                        res.getStatusCode(),
                                        res.getHeaders(),
                                        getValues(res.getValue(), "value"),
                                        getNextLink(res.getValue(), "nextLink"),
                                        null));
    }

    /**
     * Get the next page of items.
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *         String (Required)
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @param nextLink The URL to get the next list of items
     *     <p>The nextLink 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 list of strings with server paging support along with {@link PagedResponse} on successful completion
     *     of {@link Mono}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<PagedResponse<BinaryData>> listNamesNextSinglePageAsync(
            String nextLink, RequestOptions requestOptions) {
        final String accept = "application/json";
        return FluxUtil.withContext(
                        context ->
                                service.listNamesNext(
                                        nextLink, this.client.getEndpoint(), accept, requestOptions, context))
                .map(
                        res ->
                                new PagedResponseBase<>(
                                        res.getRequest(),
                                        res.getStatusCode(),
                                        res.getHeaders(),
                                        getValues(res.getValue(), "value"),
                                        getNextLink(res.getValue(), "nextLink"),
                                        null));
    }

    /**
     * Get the next page of items.
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *         String (Required)
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @param nextLink The URL to get the next list of items
     *     <p>The nextLink 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 list of strings with server paging support along with {@link PagedResponse} on successful completion
     *     of {@link Mono}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<PagedResponse<BinaryData>> listVersionsNextSinglePageAsync(
            String nextLink, RequestOptions requestOptions) {
        final String accept = "application/json";
        return FluxUtil.withContext(
                        context ->
                                service.listVersionsNext(
                                        nextLink, this.client.getEndpoint(), accept, requestOptions, context))
                .map(
                        res ->
                                new PagedResponseBase<>(
                                        res.getRequest(),
                                        res.getStatusCode(),
                                        res.getHeaders(),
                                        getValues(res.getValue(), "value"),
                                        getNextLink(res.getValue(), "nextLink"),
                                        null));
    }

    /**
     * Get the next page of items.
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *         String (Required)
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @param nextLink The URL to get the next list of items
     *     <p>The nextLink 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 list of strings with server paging support along with {@link PagedResponse} on successful completion
     *     of {@link Mono}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<PagedResponse<BinaryData>> listFilesNextSinglePageAsync(
            String nextLink, RequestOptions requestOptions) {
        final String accept = "application/json";
        return FluxUtil.withContext(
                        context ->
                                service.listFilesNext(
                                        nextLink, this.client.getEndpoint(), accept, requestOptions, context))
                .map(
                        res ->
                                new PagedResponseBase<>(
                                        res.getRequest(),
                                        res.getStatusCode(),
                                        res.getHeaders(),
                                        getValues(res.getValue(), "value"),
                                        getNextLink(res.getValue(), "nextLink"),
                                        null));
    }

    /**
     * Get the next page of items.
     *
     * <p><strong>Response Body Schema</strong>
     *
     * <pre>{@code
     * {
     *     value (Required): [
     *          (Required){
     *             operationId: String (Required)
     *             status: String(NotStarted/Running/Succeeded/Failed) (Required)
     *             update (Optional): {
     *                 updateId (Required): {
     *                     provider: String (Required)
     *                     name: String (Required)
     *                     version: String (Required)
     *                 }
     *                 description: String (Optional)
     *                 friendlyName: String (Optional)
     *             }
     *             resourceLocation: String (Optional)
     *             error (Optional): {
     *                 code: String (Required)
     *                 message: String (Required)
     *                 target: String (Optional)
     *                 details (Optional): [
     *                     (recursive schema, see above)
     *                 ]
     *                 innererror (Optional): {
     *                     code: String (Required)
     *                     message: String (Optional)
     *                     errorDetail: String (Optional)
     *                     innerError (Optional): (recursive schema, see innerError above)
     *                 }
     *                 occurredDateTime: OffsetDateTime (Optional)
     *             }
     *             traceId: String (Optional)
     *             lastActionDateTime: OffsetDateTime (Required)
     *             createdDateTime: OffsetDateTime (Required)
     *             etag: String (Optional)
     *         }
     *     ]
     *     nextLink: String (Optional)
     * }
     * }</pre>
     *
     * @param nextLink The URL to get the next list of items
     *     <p>The nextLink 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 list of operations with server paging support along with {@link PagedResponse} on successful
     *     completion of {@link Mono}.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<PagedResponse<BinaryData>> listOperationStatusesNextSinglePageAsync(
            String nextLink, RequestOptions requestOptions) {
        final String accept = "application/json";
        return FluxUtil.withContext(
                        context ->
                                service.listOperationStatusesNext(
                                        nextLink, this.client.getEndpoint(), accept, requestOptions, context))
                .map(
                        res ->
                                new PagedResponseBase<>(
                                        res.getRequest(),
                                        res.getStatusCode(),
                                        res.getHeaders(),
                                        getValues(res.getValue(), "value"),
                                        getNextLink(res.getValue(), "nextLink"),
                                        null));
    }

    private List<BinaryData> getValues(BinaryData binaryData, String path) {
        try {
            Map<?, ?> obj = binaryData.toObject(Map.class);
            List<?> values = (List<?>) obj.get(path);
            return values.stream().map(BinaryData::fromObject).collect(Collectors.toList());
        } catch (RuntimeException e) {
            return null;
        }
    }

    private String getNextLink(BinaryData binaryData, String path) {
        try {
            Map<?, ?> obj = binaryData.toObject(Map.class);
            return (String) obj.get(path);
        } catch (RuntimeException e) {
            return null;
        }
    }
}
