/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 *
 * Code generated by Microsoft (R) AutoRest Code Generator.
 */

package com.microsoft.azure.batch.protocol.implementation;

import retrofit2.Retrofit;
import com.microsoft.azure.batch.protocol.Applications;
import com.google.common.base.Joiner;
import com.google.common.reflect.TypeToken;
import com.microsoft.azure.AzureServiceFuture;
import com.microsoft.azure.batch.protocol.models.ApplicationGetHeaders;
import com.microsoft.azure.batch.protocol.models.ApplicationGetOptions;
import com.microsoft.azure.batch.protocol.models.ApplicationListHeaders;
import com.microsoft.azure.batch.protocol.models.ApplicationListNextOptions;
import com.microsoft.azure.batch.protocol.models.ApplicationListOptions;
import com.microsoft.azure.batch.protocol.models.ApplicationSummary;
import com.microsoft.azure.batch.protocol.models.BatchErrorException;
import com.microsoft.azure.batch.protocol.models.PageImpl;
import com.microsoft.azure.ListOperationCallback;
import com.microsoft.azure.Page;
import com.microsoft.azure.PagedList;
import com.microsoft.rest.DateTimeRfc1123;
import com.microsoft.rest.ServiceCallback;
import com.microsoft.rest.ServiceFuture;
import com.microsoft.rest.ServiceResponseWithHeaders;
import com.microsoft.rest.Validator;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import okhttp3.ResponseBody;
import org.joda.time.DateTime;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.Path;
import retrofit2.http.Query;
import retrofit2.http.Url;
import retrofit2.Response;
import rx.functions.Func1;
import rx.Observable;

/**
 * An instance of this class provides access to all the operations defined
 * in Applications.
 */
public class ApplicationsImpl implements Applications {
    /** The Retrofit service to perform REST calls. */
    private ApplicationsService service;
    /** The service client containing this operation class. */
    private BatchServiceClientImpl client;

    /**
     * Initializes an instance of ApplicationsImpl.
     *
     * @param retrofit the Retrofit instance built from a Retrofit Builder.
     * @param client the instance of the service client containing this operation class.
     */
    public ApplicationsImpl(Retrofit retrofit, BatchServiceClientImpl client) {
        this.service = retrofit.create(ApplicationsService.class);
        this.client = client;
    }

    /**
     * The interface defining all the services for Applications to be
     * used by Retrofit to perform actually REST calls.
     */
    interface ApplicationsService {
        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.Applications list" })
        @GET("applications")
        Observable<Response<ResponseBody>> list(@Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Query("maxresults") Integer maxResults, @Query("timeout") Integer timeout, @Header("client-request-id") UUID clientRequestId, @Header("return-client-request-id") Boolean returnClientRequestId, @Header("ocp-date") DateTimeRfc1123 ocpDate, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.Applications get" })
        @GET("applications/{applicationId}")
        Observable<Response<ResponseBody>> get(@Path("applicationId") String applicationId, @Query("api-version") String apiVersion, @Header("accept-language") String acceptLanguage, @Query("timeout") Integer timeout, @Header("client-request-id") UUID clientRequestId, @Header("return-client-request-id") Boolean returnClientRequestId, @Header("ocp-date") DateTimeRfc1123 ocpDate, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.batch.protocol.Applications listNext" })
        @GET
        Observable<Response<ResponseBody>> listNext(@Url String nextUrl, @Header("accept-language") String acceptLanguage, @Header("client-request-id") UUID clientRequestId, @Header("return-client-request-id") Boolean returnClientRequestId, @Header("ocp-date") DateTimeRfc1123 ocpDate, @Header("User-Agent") String userAgent);

    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the PagedList&lt;ApplicationSummary&gt; object if successful.
     */
    public PagedList<ApplicationSummary> list() {
        ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders> response = listSinglePageAsync().toBlocking().single();
        return new PagedList<ApplicationSummary>(response.body()) {
            @Override
            public Page<ApplicationSummary> nextPage(String nextPageLink) {
                return listNextSinglePageAsync(nextPageLink, null).toBlocking().single().body();
            }
        };
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<List<ApplicationSummary>> listAsync(final ListOperationCallback<ApplicationSummary> serviceCallback) {
        return AzureServiceFuture.fromHeaderPageResponse(
            listSinglePageAsync(),
            new Func1<String, Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> call(String nextPageLink) {
                    return listNextSinglePageAsync(nextPageLink, null);
                }
            },
            serviceCallback);
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;ApplicationSummary&gt; object
     */
    public Observable<Page<ApplicationSummary>> listAsync() {
        return listWithServiceResponseAsync()
            .map(new Func1<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>, Page<ApplicationSummary>>() {
                @Override
                public Page<ApplicationSummary> call(ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders> response) {
                    return response.body();
                }
            });
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;ApplicationSummary&gt; object
     */
    public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> listWithServiceResponseAsync() {
        return listSinglePageAsync()
            .concatMap(new Func1<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>, Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> call(ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders> page) {
                    String nextPageLink = page.body().nextPageLink();
                    if (nextPageLink == null) {
                        return Observable.just(page);
                    }
                    return Observable.just(page).concatWith(listNextWithServiceResponseAsync(nextPageLink, null));
                }
            });
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the PagedList&lt;ApplicationSummary&gt; object wrapped in {@link ServiceResponseWithHeaders} if successful.
     */
    public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> listSinglePageAsync() {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        final ApplicationListOptions applicationListOptions = null;
        Integer maxResults = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.list(this.client.apiVersion(), this.client.acceptLanguage(), maxResults, timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<PageImpl<ApplicationSummary>, ApplicationListHeaders> result = listDelegate(response);
                        return Observable.just(new ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>(result.body(), result.headers(), result.response()));
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param applicationListOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the PagedList&lt;ApplicationSummary&gt; object if successful.
     */
    public PagedList<ApplicationSummary> list(final ApplicationListOptions applicationListOptions) {
        ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders> response = listSinglePageAsync(applicationListOptions).toBlocking().single();
        return new PagedList<ApplicationSummary>(response.body()) {
            @Override
            public Page<ApplicationSummary> nextPage(String nextPageLink) {
                ApplicationListNextOptions applicationListNextOptions = null;
                if (applicationListOptions != null) {
                    applicationListNextOptions = new ApplicationListNextOptions();
                    applicationListNextOptions.withClientRequestId(applicationListOptions.clientRequestId());
                    applicationListNextOptions.withReturnClientRequestId(applicationListOptions.returnClientRequestId());
                    applicationListNextOptions.withOcpDate(applicationListOptions.ocpDate());
                }
                return listNextSinglePageAsync(nextPageLink, applicationListNextOptions).toBlocking().single().body();
            }
        };
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param applicationListOptions Additional parameters for the operation
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<List<ApplicationSummary>> listAsync(final ApplicationListOptions applicationListOptions, final ListOperationCallback<ApplicationSummary> serviceCallback) {
        return AzureServiceFuture.fromHeaderPageResponse(
            listSinglePageAsync(applicationListOptions),
            new Func1<String, Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> call(String nextPageLink) {
                    ApplicationListNextOptions applicationListNextOptions = null;
                    if (applicationListOptions != null) {
                        applicationListNextOptions = new ApplicationListNextOptions();
                        applicationListNextOptions.withClientRequestId(applicationListOptions.clientRequestId());
                        applicationListNextOptions.withReturnClientRequestId(applicationListOptions.returnClientRequestId());
                        applicationListNextOptions.withOcpDate(applicationListOptions.ocpDate());
                    }
                    return listNextSinglePageAsync(nextPageLink, applicationListNextOptions);
                }
            },
            serviceCallback);
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param applicationListOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;ApplicationSummary&gt; object
     */
    public Observable<Page<ApplicationSummary>> listAsync(final ApplicationListOptions applicationListOptions) {
        return listWithServiceResponseAsync(applicationListOptions)
            .map(new Func1<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>, Page<ApplicationSummary>>() {
                @Override
                public Page<ApplicationSummary> call(ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders> response) {
                    return response.body();
                }
            });
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param applicationListOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;ApplicationSummary&gt; object
     */
    public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> listWithServiceResponseAsync(final ApplicationListOptions applicationListOptions) {
        return listSinglePageAsync(applicationListOptions)
            .concatMap(new Func1<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>, Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> call(ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders> page) {
                    String nextPageLink = page.body().nextPageLink();
                    if (nextPageLink == null) {
                        return Observable.just(page);
                    }
                    ApplicationListNextOptions applicationListNextOptions = null;
                    if (applicationListOptions != null) {
                        applicationListNextOptions = new ApplicationListNextOptions();
                        applicationListNextOptions.withClientRequestId(applicationListOptions.clientRequestId());
                        applicationListNextOptions.withReturnClientRequestId(applicationListOptions.returnClientRequestId());
                        applicationListNextOptions.withOcpDate(applicationListOptions.ocpDate());
                    }
                    return Observable.just(page).concatWith(listNextWithServiceResponseAsync(nextPageLink, applicationListNextOptions));
                }
            });
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
    ServiceResponseWithHeaders<PageImpl<ApplicationSummary>, ApplicationListHeaders> * @param applicationListOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the PagedList&lt;ApplicationSummary&gt; object wrapped in {@link ServiceResponseWithHeaders} if successful.
     */
    public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> listSinglePageAsync(final ApplicationListOptions applicationListOptions) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        Validator.validate(applicationListOptions);
        Integer maxResults = null;
        if (applicationListOptions != null) {
            maxResults = applicationListOptions.maxResults();
        }
        Integer timeout = null;
        if (applicationListOptions != null) {
            timeout = applicationListOptions.timeout();
        }
        UUID clientRequestId = null;
        if (applicationListOptions != null) {
            clientRequestId = applicationListOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (applicationListOptions != null) {
            returnClientRequestId = applicationListOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (applicationListOptions != null) {
            ocpDate = applicationListOptions.ocpDate();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.list(this.client.apiVersion(), this.client.acceptLanguage(), maxResults, timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<PageImpl<ApplicationSummary>, ApplicationListHeaders> result = listDelegate(response);
                        return Observable.just(new ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>(result.body(), result.headers(), result.response()));
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<PageImpl<ApplicationSummary>, ApplicationListHeaders> listDelegate(Response<ResponseBody> response) throws BatchErrorException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<PageImpl<ApplicationSummary>, BatchErrorException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<PageImpl<ApplicationSummary>>() { }.getType())
                .registerError(BatchErrorException.class)
                .buildWithHeaders(response, ApplicationListHeaders.class);
    }

    /**
     * Gets information about the specified Application.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about Applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param applicationId The ID of the Application.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the ApplicationSummary object if successful.
     */
    public ApplicationSummary get(String applicationId) {
        return getWithServiceResponseAsync(applicationId).toBlocking().single().body();
    }

    /**
     * Gets information about the specified Application.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about Applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param applicationId The ID of the Application.
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<ApplicationSummary> getAsync(String applicationId, final ServiceCallback<ApplicationSummary> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(getWithServiceResponseAsync(applicationId), serviceCallback);
    }

    /**
     * Gets information about the specified Application.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about Applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param applicationId The ID of the Application.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the ApplicationSummary object
     */
    public Observable<ApplicationSummary> getAsync(String applicationId) {
        return getWithServiceResponseAsync(applicationId).map(new Func1<ServiceResponseWithHeaders<ApplicationSummary, ApplicationGetHeaders>, ApplicationSummary>() {
            @Override
            public ApplicationSummary call(ServiceResponseWithHeaders<ApplicationSummary, ApplicationGetHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Gets information about the specified Application.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about Applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param applicationId The ID of the Application.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the ApplicationSummary object
     */
    public Observable<ServiceResponseWithHeaders<ApplicationSummary, ApplicationGetHeaders>> getWithServiceResponseAsync(String applicationId) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (applicationId == null) {
            throw new IllegalArgumentException("Parameter applicationId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        final ApplicationGetOptions applicationGetOptions = null;
        Integer timeout = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.get(applicationId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<ApplicationSummary, ApplicationGetHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<ApplicationSummary, ApplicationGetHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<ApplicationSummary, ApplicationGetHeaders> clientResponse = getDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Gets information about the specified Application.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about Applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param applicationId The ID of the Application.
     * @param applicationGetOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the ApplicationSummary object if successful.
     */
    public ApplicationSummary get(String applicationId, ApplicationGetOptions applicationGetOptions) {
        return getWithServiceResponseAsync(applicationId, applicationGetOptions).toBlocking().single().body();
    }

    /**
     * Gets information about the specified Application.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about Applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param applicationId The ID of the Application.
     * @param applicationGetOptions Additional parameters for the operation
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<ApplicationSummary> getAsync(String applicationId, ApplicationGetOptions applicationGetOptions, final ServiceCallback<ApplicationSummary> serviceCallback) {
        return ServiceFuture.fromHeaderResponse(getWithServiceResponseAsync(applicationId, applicationGetOptions), serviceCallback);
    }

    /**
     * Gets information about the specified Application.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about Applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param applicationId The ID of the Application.
     * @param applicationGetOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the ApplicationSummary object
     */
    public Observable<ApplicationSummary> getAsync(String applicationId, ApplicationGetOptions applicationGetOptions) {
        return getWithServiceResponseAsync(applicationId, applicationGetOptions).map(new Func1<ServiceResponseWithHeaders<ApplicationSummary, ApplicationGetHeaders>, ApplicationSummary>() {
            @Override
            public ApplicationSummary call(ServiceResponseWithHeaders<ApplicationSummary, ApplicationGetHeaders> response) {
                return response.body();
            }
        });
    }

    /**
     * Gets information about the specified Application.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about Applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param applicationId The ID of the Application.
     * @param applicationGetOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the ApplicationSummary object
     */
    public Observable<ServiceResponseWithHeaders<ApplicationSummary, ApplicationGetHeaders>> getWithServiceResponseAsync(String applicationId, ApplicationGetOptions applicationGetOptions) {
        if (this.client.batchUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.batchUrl() is required and cannot be null.");
        }
        if (applicationId == null) {
            throw new IllegalArgumentException("Parameter applicationId is required and cannot be null.");
        }
        if (this.client.apiVersion() == null) {
            throw new IllegalArgumentException("Parameter this.client.apiVersion() is required and cannot be null.");
        }
        Validator.validate(applicationGetOptions);
        Integer timeout = null;
        if (applicationGetOptions != null) {
            timeout = applicationGetOptions.timeout();
        }
        UUID clientRequestId = null;
        if (applicationGetOptions != null) {
            clientRequestId = applicationGetOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (applicationGetOptions != null) {
            returnClientRequestId = applicationGetOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (applicationGetOptions != null) {
            ocpDate = applicationGetOptions.ocpDate();
        }
        String parameterizedHost = Joiner.on(", ").join("{batchUrl}", this.client.batchUrl());
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        return service.get(applicationId, this.client.apiVersion(), this.client.acceptLanguage(), timeout, clientRequestId, returnClientRequestId, ocpDateConverted, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<ApplicationSummary, ApplicationGetHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<ApplicationSummary, ApplicationGetHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<ApplicationSummary, ApplicationGetHeaders> clientResponse = getDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<ApplicationSummary, ApplicationGetHeaders> getDelegate(Response<ResponseBody> response) throws BatchErrorException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<ApplicationSummary, BatchErrorException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<ApplicationSummary>() { }.getType())
                .registerError(BatchErrorException.class)
                .buildWithHeaders(response, ApplicationGetHeaders.class);
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the PagedList&lt;ApplicationSummary&gt; object if successful.
     */
    public PagedList<ApplicationSummary> listNext(final String nextPageLink) {
        ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders> response = listNextSinglePageAsync(nextPageLink).toBlocking().single();
        return new PagedList<ApplicationSummary>(response.body()) {
            @Override
            public Page<ApplicationSummary> nextPage(String nextPageLink) {
                return listNextSinglePageAsync(nextPageLink, null).toBlocking().single().body();
            }
        };
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @param serviceFuture the ServiceFuture object tracking the Retrofit calls
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<List<ApplicationSummary>> listNextAsync(final String nextPageLink, final ServiceFuture<List<ApplicationSummary>> serviceFuture, final ListOperationCallback<ApplicationSummary> serviceCallback) {
        return AzureServiceFuture.fromHeaderPageResponse(
            listNextSinglePageAsync(nextPageLink),
            new Func1<String, Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> call(String nextPageLink) {
                    return listNextSinglePageAsync(nextPageLink, null);
                }
            },
            serviceCallback);
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;ApplicationSummary&gt; object
     */
    public Observable<Page<ApplicationSummary>> listNextAsync(final String nextPageLink) {
        return listNextWithServiceResponseAsync(nextPageLink)
            .map(new Func1<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>, Page<ApplicationSummary>>() {
                @Override
                public Page<ApplicationSummary> call(ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders> response) {
                    return response.body();
                }
            });
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;ApplicationSummary&gt; object
     */
    public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> listNextWithServiceResponseAsync(final String nextPageLink) {
        return listNextSinglePageAsync(nextPageLink)
            .concatMap(new Func1<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>, Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> call(ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders> page) {
                    String nextPageLink = page.body().nextPageLink();
                    if (nextPageLink == null) {
                        return Observable.just(page);
                    }
                    return Observable.just(page).concatWith(listNextWithServiceResponseAsync(nextPageLink, null));
                }
            });
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the PagedList&lt;ApplicationSummary&gt; object wrapped in {@link ServiceResponseWithHeaders} if successful.
     */
    public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> listNextSinglePageAsync(final String nextPageLink) {
        if (nextPageLink == null) {
            throw new IllegalArgumentException("Parameter nextPageLink is required and cannot be null.");
        }
        final ApplicationListNextOptions applicationListNextOptions = null;
        UUID clientRequestId = null;
        Boolean returnClientRequestId = null;
        DateTime ocpDate = null;
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        String nextUrl = String.format("%s", nextPageLink);
        return service.listNext(nextUrl, this.client.acceptLanguage(), clientRequestId, returnClientRequestId, ocpDateConverted, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<PageImpl<ApplicationSummary>, ApplicationListHeaders> result = listNextDelegate(response);
                        return Observable.just(new ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>(result.body(), result.headers(), result.response()));
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @param applicationListNextOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws BatchErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the PagedList&lt;ApplicationSummary&gt; object if successful.
     */
    public PagedList<ApplicationSummary> listNext(final String nextPageLink, final ApplicationListNextOptions applicationListNextOptions) {
        ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders> response = listNextSinglePageAsync(nextPageLink, applicationListNextOptions).toBlocking().single();
        return new PagedList<ApplicationSummary>(response.body()) {
            @Override
            public Page<ApplicationSummary> nextPage(String nextPageLink) {
                return listNextSinglePageAsync(nextPageLink, applicationListNextOptions).toBlocking().single().body();
            }
        };
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @param applicationListNextOptions Additional parameters for the operation
     * @param serviceFuture the ServiceFuture object tracking the Retrofit calls
     * @param serviceCallback the async ServiceCallback to handle successful and failed responses.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceFuture} object
     */
    public ServiceFuture<List<ApplicationSummary>> listNextAsync(final String nextPageLink, final ApplicationListNextOptions applicationListNextOptions, final ServiceFuture<List<ApplicationSummary>> serviceFuture, final ListOperationCallback<ApplicationSummary> serviceCallback) {
        return AzureServiceFuture.fromHeaderPageResponse(
            listNextSinglePageAsync(nextPageLink, applicationListNextOptions),
            new Func1<String, Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> call(String nextPageLink) {
                    return listNextSinglePageAsync(nextPageLink, applicationListNextOptions);
                }
            },
            serviceCallback);
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @param applicationListNextOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;ApplicationSummary&gt; object
     */
    public Observable<Page<ApplicationSummary>> listNextAsync(final String nextPageLink, final ApplicationListNextOptions applicationListNextOptions) {
        return listNextWithServiceResponseAsync(nextPageLink, applicationListNextOptions)
            .map(new Func1<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>, Page<ApplicationSummary>>() {
                @Override
                public Page<ApplicationSummary> call(ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders> response) {
                    return response.body();
                }
            });
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
     * @param nextPageLink The NextLink from the previous successful call to List operation.
     * @param applicationListNextOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PagedList&lt;ApplicationSummary&gt; object
     */
    public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> listNextWithServiceResponseAsync(final String nextPageLink, final ApplicationListNextOptions applicationListNextOptions) {
        return listNextSinglePageAsync(nextPageLink, applicationListNextOptions)
            .concatMap(new Func1<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>, Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> call(ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders> page) {
                    String nextPageLink = page.body().nextPageLink();
                    if (nextPageLink == null) {
                        return Observable.just(page);
                    }
                    return Observable.just(page).concatWith(listNextWithServiceResponseAsync(nextPageLink, applicationListNextOptions));
                }
            });
    }

    /**
     * Lists all of the applications available in the specified Account.
     * This operation returns only Applications and versions that are available for use on Compute Nodes; that is, that can be used in an Package reference. For administrator information about applications and versions that are not yet available to Compute Nodes, use the Azure portal or the Azure Resource Manager API.
     *
    ServiceResponseWithHeaders<PageImpl<ApplicationSummary>, ApplicationListHeaders> * @param nextPageLink The NextLink from the previous successful call to List operation.
    ServiceResponseWithHeaders<PageImpl<ApplicationSummary>, ApplicationListHeaders> * @param applicationListNextOptions Additional parameters for the operation
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the PagedList&lt;ApplicationSummary&gt; object wrapped in {@link ServiceResponseWithHeaders} if successful.
     */
    public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> listNextSinglePageAsync(final String nextPageLink, final ApplicationListNextOptions applicationListNextOptions) {
        if (nextPageLink == null) {
            throw new IllegalArgumentException("Parameter nextPageLink is required and cannot be null.");
        }
        Validator.validate(applicationListNextOptions);
        UUID clientRequestId = null;
        if (applicationListNextOptions != null) {
            clientRequestId = applicationListNextOptions.clientRequestId();
        }
        Boolean returnClientRequestId = null;
        if (applicationListNextOptions != null) {
            returnClientRequestId = applicationListNextOptions.returnClientRequestId();
        }
        DateTime ocpDate = null;
        if (applicationListNextOptions != null) {
            ocpDate = applicationListNextOptions.ocpDate();
        }
        DateTimeRfc1123 ocpDateConverted = null;
        if (ocpDate != null) {
            ocpDateConverted = new DateTimeRfc1123(ocpDate);
        }
        String nextUrl = String.format("%s", nextPageLink);
        return service.listNext(nextUrl, this.client.acceptLanguage(), clientRequestId, returnClientRequestId, ocpDateConverted, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>>>() {
                @Override
                public Observable<ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponseWithHeaders<PageImpl<ApplicationSummary>, ApplicationListHeaders> result = listNextDelegate(response);
                        return Observable.just(new ServiceResponseWithHeaders<Page<ApplicationSummary>, ApplicationListHeaders>(result.body(), result.headers(), result.response()));
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponseWithHeaders<PageImpl<ApplicationSummary>, ApplicationListHeaders> listNextDelegate(Response<ResponseBody> response) throws BatchErrorException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<PageImpl<ApplicationSummary>, BatchErrorException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<PageImpl<ApplicationSummary>>() { }.getType())
                .registerError(BatchErrorException.class)
                .buildWithHeaders(response, ApplicationListHeaders.class);
    }

}
