/**
 * 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.cognitiveservices.language.luis.authoring.implementation;

import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.CloneOptionalParameter;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.ListVersionsOptionalParameter;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.UpdateVersionsOptionalParameter;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.ImportMethodVersionsOptionalParameter;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.ImportV2AppVersionsOptionalParameter;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.ImportLuFormatVersionsOptionalParameter;
import retrofit2.Retrofit;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.Versions;
import com.google.common.base.Joiner;
import com.google.common.reflect.TypeToken;
import com.microsoft.azure.CloudException;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.ErrorResponseException;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.LuisApp;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.LuisAppV2;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.OperationStatus;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.TaskUpdateObject;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.VersionInfo;
import com.microsoft.rest.ServiceCallback;
import com.microsoft.rest.ServiceFuture;
import com.microsoft.rest.ServiceResponse;
import com.microsoft.rest.Validator;
import java.io.InputStream;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import okhttp3.ResponseBody;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.HTTP;
import retrofit2.http.Path;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Query;
import retrofit2.http.Streaming;
import retrofit2.Response;
import rx.functions.Func1;
import rx.Observable;

/**
 * An instance of this class provides access to all the operations defined
 * in Versions.
 */
public class VersionsImpl implements Versions {
    /** The Retrofit service to perform REST calls. */
    private VersionsService service;
    /** The service client containing this operation class. */
    private LUISAuthoringClientImpl client;

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

    /**
     * The interface defining all the services for Versions to be
     * used by Retrofit to perform actually REST calls.
     */
    interface VersionsService {
        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.cognitiveservices.language.luis.authoring.Versions clone" })
        @POST("apps/{appId}/versions/{versionId}/clone")
        Observable<Response<ResponseBody>> clone(@Path("appId") UUID appId, @Path("versionId") String versionId, @Header("accept-language") String acceptLanguage, @Body TaskUpdateObject versionCloneObject, @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.cognitiveservices.language.luis.authoring.Versions list" })
        @GET("apps/{appId}/versions")
        Observable<Response<ResponseBody>> list(@Path("appId") UUID appId, @Query("skip") Integer skip, @Query("take") Integer take, @Header("accept-language") String acceptLanguage, @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.cognitiveservices.language.luis.authoring.Versions get" })
        @GET("apps/{appId}/versions/{versionId}/")
        Observable<Response<ResponseBody>> get(@Path("appId") UUID appId, @Path("versionId") String versionId, @Header("accept-language") String acceptLanguage, @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.cognitiveservices.language.luis.authoring.Versions update" })
        @PUT("apps/{appId}/versions/{versionId}/")
        Observable<Response<ResponseBody>> update(@Path("appId") UUID appId, @Path("versionId") String versionId, @Header("accept-language") String acceptLanguage, @Body TaskUpdateObject versionUpdateObject, @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.cognitiveservices.language.luis.authoring.Versions delete" })
        @HTTP(path = "apps/{appId}/versions/{versionId}/", method = "DELETE", hasBody = true)
        Observable<Response<ResponseBody>> delete(@Path("appId") UUID appId, @Path("versionId") String versionId, @Header("accept-language") String acceptLanguage, @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.cognitiveservices.language.luis.authoring.Versions export" })
        @GET("apps/{appId}/versions/{versionId}/export")
        Observable<Response<ResponseBody>> export(@Path("appId") UUID appId, @Path("versionId") String versionId, @Header("accept-language") String acceptLanguage, @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.cognitiveservices.language.luis.authoring.Versions importMethod" })
        @POST("apps/{appId}/versions/import")
        Observable<Response<ResponseBody>> importMethod(@Path("appId") UUID appId, @Query("versionId") String versionId, @Body LuisApp luisApp, @Header("accept-language") String acceptLanguage, @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.cognitiveservices.language.luis.authoring.Versions deleteUnlabelledUtterance" })
        @HTTP(path = "apps/{appId}/versions/{versionId}/suggest", method = "DELETE", hasBody = true)
        Observable<Response<ResponseBody>> deleteUnlabelledUtterance(@Path("appId") UUID appId, @Path("versionId") String versionId, @Body String utterance, @Header("accept-language") String acceptLanguage, @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.cognitiveservices.language.luis.authoring.Versions importV2App" })
        @POST("apps/{appId}/versions/import")
        Observable<Response<ResponseBody>> importV2App(@Path("appId") UUID appId, @Query("versionId") String versionId, @Body LuisAppV2 luisAppV2, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

        @Headers({ "Content-Type: text/plain", "x-ms-logging-context: com.microsoft.azure.cognitiveservices.language.luis.authoring.Versions importLuFormat" })
        @POST("apps/{appId}/versions/import")
        Observable<Response<ResponseBody>> importLuFormat(@Path("appId") UUID appId, @Query("versionId") String versionId, @Body String luisAppLu, @Header("accept-language") String acceptLanguage, @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.cognitiveservices.language.luis.authoring.Versions exportLuFormat" })
        @GET("apps/{appId}/versions/{versionId}/export")
        @Streaming
        Observable<Response<ResponseBody>> exportLuFormat(@Path("appId") UUID appId, @Path("versionId") String versionId, @Query("format") String format, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

    }


    /**
     * Creates a new version from the selected version.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param cloneOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorResponseException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the String object if successful.
     */
    public String clone(UUID appId, String versionId, CloneOptionalParameter cloneOptionalParameter) {
        return cloneWithServiceResponseAsync(appId, versionId, cloneOptionalParameter).toBlocking().single().body();
    }

    /**
     * Creates a new version from the selected version.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param cloneOptionalParameter the object representing the optional parameters to be set before calling this 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<String> cloneAsync(UUID appId, String versionId, CloneOptionalParameter cloneOptionalParameter, final ServiceCallback<String> serviceCallback) {
        return ServiceFuture.fromResponse(cloneWithServiceResponseAsync(appId, versionId, cloneOptionalParameter), serviceCallback);
    }

    /**
     * Creates a new version from the selected version.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param cloneOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the String object
     */
    public Observable<String> cloneAsync(UUID appId, String versionId, CloneOptionalParameter cloneOptionalParameter) {
        return cloneWithServiceResponseAsync(appId, versionId, cloneOptionalParameter).map(new Func1<ServiceResponse<String>, String>() {
            @Override
            public String call(ServiceResponse<String> response) {
                return response.body();
            }
        });
    }

    /**
     * Creates a new version from the selected version.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param cloneOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the String object
     */
    public Observable<ServiceResponse<String>> cloneWithServiceResponseAsync(UUID appId, String versionId, CloneOptionalParameter cloneOptionalParameter) {
        if (this.client.endpoint() == null) {
            throw new IllegalArgumentException("Parameter this.client.endpoint() is required and cannot be null.");
        }
        if (appId == null) {
            throw new IllegalArgumentException("Parameter appId is required and cannot be null.");
        }
        if (versionId == null) {
            throw new IllegalArgumentException("Parameter versionId is required and cannot be null.");
        }
        final String version = cloneOptionalParameter != null ? cloneOptionalParameter.version() : null;

        return cloneWithServiceResponseAsync(appId, versionId, version);
    }

    /**
     * Creates a new version from the selected version.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param version The new version for the cloned model.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the String object
     */
    public Observable<ServiceResponse<String>> cloneWithServiceResponseAsync(UUID appId, String versionId, String version) {
        if (this.client.endpoint() == null) {
            throw new IllegalArgumentException("Parameter this.client.endpoint() is required and cannot be null.");
        }
        if (appId == null) {
            throw new IllegalArgumentException("Parameter appId is required and cannot be null.");
        }
        if (versionId == null) {
            throw new IllegalArgumentException("Parameter versionId is required and cannot be null.");
        }
        TaskUpdateObject versionCloneObject = new TaskUpdateObject();
        versionCloneObject.withVersion(version);
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.clone(appId, versionId, this.client.acceptLanguage(), versionCloneObject, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<String>>>() {
                @Override
                public Observable<ServiceResponse<String>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<String> clientResponse = cloneDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponse<String> cloneDelegate(Response<ResponseBody> response) throws ErrorResponseException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<String, ErrorResponseException>newInstance(this.client.serializerAdapter())
                .register(201, new TypeToken<String>() { }.getType())
                .registerError(ErrorResponseException.class)
                .build(response);
    }

    @Override
    public VersionsCloneParameters clone() {
        return new VersionsCloneParameters(this);
    }

    /**
     * Internal class implementing VersionsCloneDefinition.
     */
    class VersionsCloneParameters implements VersionsCloneDefinition {
        private VersionsImpl parent;
        private UUID appId;
        private String versionId;
        private String version;

        /**
         * Constructor.
         * @param parent the parent object.
         */
        VersionsCloneParameters(VersionsImpl parent) {
            this.parent = parent;
        }

        @Override
        public VersionsCloneParameters withAppId(UUID appId) {
            this.appId = appId;
            return this;
        }

        @Override
        public VersionsCloneParameters withVersionId(String versionId) {
            this.versionId = versionId;
            return this;
        }

        @Override
        public VersionsCloneParameters withVersion(String version) {
            this.version = version;
            return this;
        }

        @Override
        public String execute() {
        return cloneWithServiceResponseAsync(appId, versionId, version).toBlocking().single().body();
    }

        @Override
        public Observable<String> executeAsync() {
            return cloneWithServiceResponseAsync(appId, versionId, version).map(new Func1<ServiceResponse<String>, String>() {
                @Override
                public String call(ServiceResponse<String> response) {
                    return response.body();
                }
            });
        }
    }


    /**
     * Gets a list of versions for this application ID.
     *
     * @param appId The application ID.
     * @param listOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorResponseException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the List&lt;VersionInfo&gt; object if successful.
     */
    public List<VersionInfo> list(UUID appId, ListVersionsOptionalParameter listOptionalParameter) {
        return listWithServiceResponseAsync(appId, listOptionalParameter).toBlocking().single().body();
    }

    /**
     * Gets a list of versions for this application ID.
     *
     * @param appId The application ID.
     * @param listOptionalParameter the object representing the optional parameters to be set before calling this 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<VersionInfo>> listAsync(UUID appId, ListVersionsOptionalParameter listOptionalParameter, final ServiceCallback<List<VersionInfo>> serviceCallback) {
        return ServiceFuture.fromResponse(listWithServiceResponseAsync(appId, listOptionalParameter), serviceCallback);
    }

    /**
     * Gets a list of versions for this application ID.
     *
     * @param appId The application ID.
     * @param listOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the List&lt;VersionInfo&gt; object
     */
    public Observable<List<VersionInfo>> listAsync(UUID appId, ListVersionsOptionalParameter listOptionalParameter) {
        return listWithServiceResponseAsync(appId, listOptionalParameter).map(new Func1<ServiceResponse<List<VersionInfo>>, List<VersionInfo>>() {
            @Override
            public List<VersionInfo> call(ServiceResponse<List<VersionInfo>> response) {
                return response.body();
            }
        });
    }

    /**
     * Gets a list of versions for this application ID.
     *
     * @param appId The application ID.
     * @param listOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the List&lt;VersionInfo&gt; object
     */
    public Observable<ServiceResponse<List<VersionInfo>>> listWithServiceResponseAsync(UUID appId, ListVersionsOptionalParameter listOptionalParameter) {
        if (this.client.endpoint() == null) {
            throw new IllegalArgumentException("Parameter this.client.endpoint() is required and cannot be null.");
        }
        if (appId == null) {
            throw new IllegalArgumentException("Parameter appId is required and cannot be null.");
        }
        final Integer skip = listOptionalParameter != null ? listOptionalParameter.skip() : null;
        final Integer take = listOptionalParameter != null ? listOptionalParameter.take() : null;

        return listWithServiceResponseAsync(appId, skip, take);
    }

    /**
     * Gets a list of versions for this application ID.
     *
     * @param appId The application ID.
     * @param skip The number of entries to skip. Default value is 0.
     * @param take The number of entries to return. Maximum page size is 500. Default is 100.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the List&lt;VersionInfo&gt; object
     */
    public Observable<ServiceResponse<List<VersionInfo>>> listWithServiceResponseAsync(UUID appId, Integer skip, Integer take) {
        if (this.client.endpoint() == null) {
            throw new IllegalArgumentException("Parameter this.client.endpoint() is required and cannot be null.");
        }
        if (appId == null) {
            throw new IllegalArgumentException("Parameter appId is required and cannot be null.");
        }
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.list(appId, skip, take, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<List<VersionInfo>>>>() {
                @Override
                public Observable<ServiceResponse<List<VersionInfo>>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<List<VersionInfo>> clientResponse = listDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponse<List<VersionInfo>> listDelegate(Response<ResponseBody> response) throws ErrorResponseException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<List<VersionInfo>, ErrorResponseException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<List<VersionInfo>>() { }.getType())
                .registerError(ErrorResponseException.class)
                .build(response);
    }

    @Override
    public VersionsListParameters list() {
        return new VersionsListParameters(this);
    }

    /**
     * Internal class implementing VersionsListDefinition.
     */
    class VersionsListParameters implements VersionsListDefinition {
        private VersionsImpl parent;
        private UUID appId;
        private Integer skip;
        private Integer take;

        /**
         * Constructor.
         * @param parent the parent object.
         */
        VersionsListParameters(VersionsImpl parent) {
            this.parent = parent;
        }

        @Override
        public VersionsListParameters withAppId(UUID appId) {
            this.appId = appId;
            return this;
        }

        @Override
        public VersionsListParameters withSkip(Integer skip) {
            this.skip = skip;
            return this;
        }

        @Override
        public VersionsListParameters withTake(Integer take) {
            this.take = take;
            return this;
        }

        @Override
        public List<VersionInfo> execute() {
        return listWithServiceResponseAsync(appId, skip, take).toBlocking().single().body();
    }

        @Override
        public Observable<List<VersionInfo>> executeAsync() {
            return listWithServiceResponseAsync(appId, skip, take).map(new Func1<ServiceResponse<List<VersionInfo>>, List<VersionInfo>>() {
                @Override
                public List<VersionInfo> call(ServiceResponse<List<VersionInfo>> response) {
                    return response.body();
                }
            });
        }
    }

    /**
     * Gets the version information such as date created, last modified date, endpoint URL, count of intents and entities, training and publishing status.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorResponseException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the VersionInfo object if successful.
     */
    public VersionInfo get(UUID appId, String versionId) {
        return getWithServiceResponseAsync(appId, versionId).toBlocking().single().body();
    }

    /**
     * Gets the version information such as date created, last modified date, endpoint URL, count of intents and entities, training and publishing status.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @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<VersionInfo> getAsync(UUID appId, String versionId, final ServiceCallback<VersionInfo> serviceCallback) {
        return ServiceFuture.fromResponse(getWithServiceResponseAsync(appId, versionId), serviceCallback);
    }

    /**
     * Gets the version information such as date created, last modified date, endpoint URL, count of intents and entities, training and publishing status.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the VersionInfo object
     */
    public Observable<VersionInfo> getAsync(UUID appId, String versionId) {
        return getWithServiceResponseAsync(appId, versionId).map(new Func1<ServiceResponse<VersionInfo>, VersionInfo>() {
            @Override
            public VersionInfo call(ServiceResponse<VersionInfo> response) {
                return response.body();
            }
        });
    }

    /**
     * Gets the version information such as date created, last modified date, endpoint URL, count of intents and entities, training and publishing status.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the VersionInfo object
     */
    public Observable<ServiceResponse<VersionInfo>> getWithServiceResponseAsync(UUID appId, String versionId) {
        if (this.client.endpoint() == null) {
            throw new IllegalArgumentException("Parameter this.client.endpoint() is required and cannot be null.");
        }
        if (appId == null) {
            throw new IllegalArgumentException("Parameter appId is required and cannot be null.");
        }
        if (versionId == null) {
            throw new IllegalArgumentException("Parameter versionId is required and cannot be null.");
        }
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.get(appId, versionId, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<VersionInfo>>>() {
                @Override
                public Observable<ServiceResponse<VersionInfo>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<VersionInfo> clientResponse = getDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponse<VersionInfo> getDelegate(Response<ResponseBody> response) throws ErrorResponseException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<VersionInfo, ErrorResponseException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<VersionInfo>() { }.getType())
                .registerError(ErrorResponseException.class)
                .build(response);
    }


    /**
     * Updates the name or description of the application version.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param updateOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorResponseException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the OperationStatus object if successful.
     */
    public OperationStatus update(UUID appId, String versionId, UpdateVersionsOptionalParameter updateOptionalParameter) {
        return updateWithServiceResponseAsync(appId, versionId, updateOptionalParameter).toBlocking().single().body();
    }

    /**
     * Updates the name or description of the application version.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param updateOptionalParameter the object representing the optional parameters to be set before calling this 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<OperationStatus> updateAsync(UUID appId, String versionId, UpdateVersionsOptionalParameter updateOptionalParameter, final ServiceCallback<OperationStatus> serviceCallback) {
        return ServiceFuture.fromResponse(updateWithServiceResponseAsync(appId, versionId, updateOptionalParameter), serviceCallback);
    }

    /**
     * Updates the name or description of the application version.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param updateOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the OperationStatus object
     */
    public Observable<OperationStatus> updateAsync(UUID appId, String versionId, UpdateVersionsOptionalParameter updateOptionalParameter) {
        return updateWithServiceResponseAsync(appId, versionId, updateOptionalParameter).map(new Func1<ServiceResponse<OperationStatus>, OperationStatus>() {
            @Override
            public OperationStatus call(ServiceResponse<OperationStatus> response) {
                return response.body();
            }
        });
    }

    /**
     * Updates the name or description of the application version.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param updateOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the OperationStatus object
     */
    public Observable<ServiceResponse<OperationStatus>> updateWithServiceResponseAsync(UUID appId, String versionId, UpdateVersionsOptionalParameter updateOptionalParameter) {
        if (this.client.endpoint() == null) {
            throw new IllegalArgumentException("Parameter this.client.endpoint() is required and cannot be null.");
        }
        if (appId == null) {
            throw new IllegalArgumentException("Parameter appId is required and cannot be null.");
        }
        if (versionId == null) {
            throw new IllegalArgumentException("Parameter versionId is required and cannot be null.");
        }
        final String version = updateOptionalParameter != null ? updateOptionalParameter.version() : null;

        return updateWithServiceResponseAsync(appId, versionId, version);
    }

    /**
     * Updates the name or description of the application version.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param version The new version for the cloned model.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the OperationStatus object
     */
    public Observable<ServiceResponse<OperationStatus>> updateWithServiceResponseAsync(UUID appId, String versionId, String version) {
        if (this.client.endpoint() == null) {
            throw new IllegalArgumentException("Parameter this.client.endpoint() is required and cannot be null.");
        }
        if (appId == null) {
            throw new IllegalArgumentException("Parameter appId is required and cannot be null.");
        }
        if (versionId == null) {
            throw new IllegalArgumentException("Parameter versionId is required and cannot be null.");
        }
        TaskUpdateObject versionUpdateObject = new TaskUpdateObject();
        versionUpdateObject.withVersion(version);
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.update(appId, versionId, this.client.acceptLanguage(), versionUpdateObject, parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<OperationStatus>>>() {
                @Override
                public Observable<ServiceResponse<OperationStatus>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<OperationStatus> clientResponse = updateDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponse<OperationStatus> updateDelegate(Response<ResponseBody> response) throws ErrorResponseException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<OperationStatus, ErrorResponseException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<OperationStatus>() { }.getType())
                .registerError(ErrorResponseException.class)
                .build(response);
    }

    @Override
    public VersionsUpdateParameters update() {
        return new VersionsUpdateParameters(this);
    }

    /**
     * Internal class implementing VersionsUpdateDefinition.
     */
    class VersionsUpdateParameters implements VersionsUpdateDefinition {
        private VersionsImpl parent;
        private UUID appId;
        private String versionId;
        private String version;

        /**
         * Constructor.
         * @param parent the parent object.
         */
        VersionsUpdateParameters(VersionsImpl parent) {
            this.parent = parent;
        }

        @Override
        public VersionsUpdateParameters withAppId(UUID appId) {
            this.appId = appId;
            return this;
        }

        @Override
        public VersionsUpdateParameters withVersionId(String versionId) {
            this.versionId = versionId;
            return this;
        }

        @Override
        public VersionsUpdateParameters withVersion(String version) {
            this.version = version;
            return this;
        }

        @Override
        public OperationStatus execute() {
        return updateWithServiceResponseAsync(appId, versionId, version).toBlocking().single().body();
    }

        @Override
        public Observable<OperationStatus> executeAsync() {
            return updateWithServiceResponseAsync(appId, versionId, version).map(new Func1<ServiceResponse<OperationStatus>, OperationStatus>() {
                @Override
                public OperationStatus call(ServiceResponse<OperationStatus> response) {
                    return response.body();
                }
            });
        }
    }

    /**
     * Deletes an application version.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorResponseException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the OperationStatus object if successful.
     */
    public OperationStatus delete(UUID appId, String versionId) {
        return deleteWithServiceResponseAsync(appId, versionId).toBlocking().single().body();
    }

    /**
     * Deletes an application version.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @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<OperationStatus> deleteAsync(UUID appId, String versionId, final ServiceCallback<OperationStatus> serviceCallback) {
        return ServiceFuture.fromResponse(deleteWithServiceResponseAsync(appId, versionId), serviceCallback);
    }

    /**
     * Deletes an application version.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the OperationStatus object
     */
    public Observable<OperationStatus> deleteAsync(UUID appId, String versionId) {
        return deleteWithServiceResponseAsync(appId, versionId).map(new Func1<ServiceResponse<OperationStatus>, OperationStatus>() {
            @Override
            public OperationStatus call(ServiceResponse<OperationStatus> response) {
                return response.body();
            }
        });
    }

    /**
     * Deletes an application version.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the OperationStatus object
     */
    public Observable<ServiceResponse<OperationStatus>> deleteWithServiceResponseAsync(UUID appId, String versionId) {
        if (this.client.endpoint() == null) {
            throw new IllegalArgumentException("Parameter this.client.endpoint() is required and cannot be null.");
        }
        if (appId == null) {
            throw new IllegalArgumentException("Parameter appId is required and cannot be null.");
        }
        if (versionId == null) {
            throw new IllegalArgumentException("Parameter versionId is required and cannot be null.");
        }
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.delete(appId, versionId, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<OperationStatus>>>() {
                @Override
                public Observable<ServiceResponse<OperationStatus>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<OperationStatus> clientResponse = deleteDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponse<OperationStatus> deleteDelegate(Response<ResponseBody> response) throws ErrorResponseException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<OperationStatus, ErrorResponseException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<OperationStatus>() { }.getType())
                .registerError(ErrorResponseException.class)
                .build(response);
    }

    /**
     * Exports a LUIS application to JSON format.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorResponseException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the LuisApp object if successful.
     */
    public LuisApp export(UUID appId, String versionId) {
        return exportWithServiceResponseAsync(appId, versionId).toBlocking().single().body();
    }

    /**
     * Exports a LUIS application to JSON format.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @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<LuisApp> exportAsync(UUID appId, String versionId, final ServiceCallback<LuisApp> serviceCallback) {
        return ServiceFuture.fromResponse(exportWithServiceResponseAsync(appId, versionId), serviceCallback);
    }

    /**
     * Exports a LUIS application to JSON format.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the LuisApp object
     */
    public Observable<LuisApp> exportAsync(UUID appId, String versionId) {
        return exportWithServiceResponseAsync(appId, versionId).map(new Func1<ServiceResponse<LuisApp>, LuisApp>() {
            @Override
            public LuisApp call(ServiceResponse<LuisApp> response) {
                return response.body();
            }
        });
    }

    /**
     * Exports a LUIS application to JSON format.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the LuisApp object
     */
    public Observable<ServiceResponse<LuisApp>> exportWithServiceResponseAsync(UUID appId, String versionId) {
        if (this.client.endpoint() == null) {
            throw new IllegalArgumentException("Parameter this.client.endpoint() is required and cannot be null.");
        }
        if (appId == null) {
            throw new IllegalArgumentException("Parameter appId is required and cannot be null.");
        }
        if (versionId == null) {
            throw new IllegalArgumentException("Parameter versionId is required and cannot be null.");
        }
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.export(appId, versionId, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<LuisApp>>>() {
                @Override
                public Observable<ServiceResponse<LuisApp>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<LuisApp> clientResponse = exportDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponse<LuisApp> exportDelegate(Response<ResponseBody> response) throws ErrorResponseException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<LuisApp, ErrorResponseException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<LuisApp>() { }.getType())
                .registerError(ErrorResponseException.class)
                .build(response);
    }


    /**
     * Imports a new version into a LUIS application.
     *
     * @param appId The application ID.
     * @param luisApp A LUIS application structure.
     * @param importMethodOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorResponseException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the String object if successful.
     */
    public String importMethod(UUID appId, LuisApp luisApp, ImportMethodVersionsOptionalParameter importMethodOptionalParameter) {
        return importMethodWithServiceResponseAsync(appId, luisApp, importMethodOptionalParameter).toBlocking().single().body();
    }

    /**
     * Imports a new version into a LUIS application.
     *
     * @param appId The application ID.
     * @param luisApp A LUIS application structure.
     * @param importMethodOptionalParameter the object representing the optional parameters to be set before calling this 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<String> importMethodAsync(UUID appId, LuisApp luisApp, ImportMethodVersionsOptionalParameter importMethodOptionalParameter, final ServiceCallback<String> serviceCallback) {
        return ServiceFuture.fromResponse(importMethodWithServiceResponseAsync(appId, luisApp, importMethodOptionalParameter), serviceCallback);
    }

    /**
     * Imports a new version into a LUIS application.
     *
     * @param appId The application ID.
     * @param luisApp A LUIS application structure.
     * @param importMethodOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the String object
     */
    public Observable<String> importMethodAsync(UUID appId, LuisApp luisApp, ImportMethodVersionsOptionalParameter importMethodOptionalParameter) {
        return importMethodWithServiceResponseAsync(appId, luisApp, importMethodOptionalParameter).map(new Func1<ServiceResponse<String>, String>() {
            @Override
            public String call(ServiceResponse<String> response) {
                return response.body();
            }
        });
    }

    /**
     * Imports a new version into a LUIS application.
     *
     * @param appId The application ID.
     * @param luisApp A LUIS application structure.
     * @param importMethodOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the String object
     */
    public Observable<ServiceResponse<String>> importMethodWithServiceResponseAsync(UUID appId, LuisApp luisApp, ImportMethodVersionsOptionalParameter importMethodOptionalParameter) {
        if (this.client.endpoint() == null) {
            throw new IllegalArgumentException("Parameter this.client.endpoint() is required and cannot be null.");
        }
        if (appId == null) {
            throw new IllegalArgumentException("Parameter appId is required and cannot be null.");
        }
        if (luisApp == null) {
            throw new IllegalArgumentException("Parameter luisApp is required and cannot be null.");
        }
        Validator.validate(luisApp);
        final String versionId = importMethodOptionalParameter != null ? importMethodOptionalParameter.versionId() : null;

        return importMethodWithServiceResponseAsync(appId, luisApp, versionId);
    }

    /**
     * Imports a new version into a LUIS application.
     *
     * @param appId The application ID.
     * @param luisApp A LUIS application structure.
     * @param versionId The new versionId to import. If not specified, the versionId will be read from the imported object.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the String object
     */
    public Observable<ServiceResponse<String>> importMethodWithServiceResponseAsync(UUID appId, LuisApp luisApp, String versionId) {
        if (this.client.endpoint() == null) {
            throw new IllegalArgumentException("Parameter this.client.endpoint() is required and cannot be null.");
        }
        if (appId == null) {
            throw new IllegalArgumentException("Parameter appId is required and cannot be null.");
        }
        if (luisApp == null) {
            throw new IllegalArgumentException("Parameter luisApp is required and cannot be null.");
        }
        Validator.validate(luisApp);
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.importMethod(appId, versionId, luisApp, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<String>>>() {
                @Override
                public Observable<ServiceResponse<String>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<String> clientResponse = importMethodDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponse<String> importMethodDelegate(Response<ResponseBody> response) throws ErrorResponseException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<String, ErrorResponseException>newInstance(this.client.serializerAdapter())
                .register(201, new TypeToken<String>() { }.getType())
                .registerError(ErrorResponseException.class)
                .build(response);
    }

    @Override
    public VersionsImportMethodParameters importMethod() {
        return new VersionsImportMethodParameters(this);
    }

    /**
     * Internal class implementing VersionsImportMethodDefinition.
     */
    class VersionsImportMethodParameters implements VersionsImportMethodDefinition {
        private VersionsImpl parent;
        private UUID appId;
        private LuisApp luisApp;
        private String versionId;

        /**
         * Constructor.
         * @param parent the parent object.
         */
        VersionsImportMethodParameters(VersionsImpl parent) {
            this.parent = parent;
        }

        @Override
        public VersionsImportMethodParameters withAppId(UUID appId) {
            this.appId = appId;
            return this;
        }

        @Override
        public VersionsImportMethodParameters withLuisApp(LuisApp luisApp) {
            this.luisApp = luisApp;
            return this;
        }

        @Override
        public VersionsImportMethodParameters withVersionId(String versionId) {
            this.versionId = versionId;
            return this;
        }

        @Override
        public String execute() {
        return importMethodWithServiceResponseAsync(appId, luisApp, versionId).toBlocking().single().body();
    }

        @Override
        public Observable<String> executeAsync() {
            return importMethodWithServiceResponseAsync(appId, luisApp, versionId).map(new Func1<ServiceResponse<String>, String>() {
                @Override
                public String call(ServiceResponse<String> response) {
                    return response.body();
                }
            });
        }
    }

    /**
     * Deleted an unlabelled utterance in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param utterance The utterance text to delete.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorResponseException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the OperationStatus object if successful.
     */
    public OperationStatus deleteUnlabelledUtterance(UUID appId, String versionId, String utterance) {
        return deleteUnlabelledUtteranceWithServiceResponseAsync(appId, versionId, utterance).toBlocking().single().body();
    }

    /**
     * Deleted an unlabelled utterance in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param utterance The utterance text to delete.
     * @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<OperationStatus> deleteUnlabelledUtteranceAsync(UUID appId, String versionId, String utterance, final ServiceCallback<OperationStatus> serviceCallback) {
        return ServiceFuture.fromResponse(deleteUnlabelledUtteranceWithServiceResponseAsync(appId, versionId, utterance), serviceCallback);
    }

    /**
     * Deleted an unlabelled utterance in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param utterance The utterance text to delete.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the OperationStatus object
     */
    public Observable<OperationStatus> deleteUnlabelledUtteranceAsync(UUID appId, String versionId, String utterance) {
        return deleteUnlabelledUtteranceWithServiceResponseAsync(appId, versionId, utterance).map(new Func1<ServiceResponse<OperationStatus>, OperationStatus>() {
            @Override
            public OperationStatus call(ServiceResponse<OperationStatus> response) {
                return response.body();
            }
        });
    }

    /**
     * Deleted an unlabelled utterance in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param utterance The utterance text to delete.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the OperationStatus object
     */
    public Observable<ServiceResponse<OperationStatus>> deleteUnlabelledUtteranceWithServiceResponseAsync(UUID appId, String versionId, String utterance) {
        if (this.client.endpoint() == null) {
            throw new IllegalArgumentException("Parameter this.client.endpoint() is required and cannot be null.");
        }
        if (appId == null) {
            throw new IllegalArgumentException("Parameter appId is required and cannot be null.");
        }
        if (versionId == null) {
            throw new IllegalArgumentException("Parameter versionId is required and cannot be null.");
        }
        if (utterance == null) {
            throw new IllegalArgumentException("Parameter utterance is required and cannot be null.");
        }
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.deleteUnlabelledUtterance(appId, versionId, utterance, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<OperationStatus>>>() {
                @Override
                public Observable<ServiceResponse<OperationStatus>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<OperationStatus> clientResponse = deleteUnlabelledUtteranceDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponse<OperationStatus> deleteUnlabelledUtteranceDelegate(Response<ResponseBody> response) throws ErrorResponseException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<OperationStatus, ErrorResponseException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<OperationStatus>() { }.getType())
                .registerError(ErrorResponseException.class)
                .build(response);
    }


    /**
     * Imports a new version into a LUIS application.
     *
     * @param appId The application ID.
     * @param luisAppV2 A LUIS application structure.
     * @param importV2AppOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorResponseException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the String object if successful.
     */
    public String importV2App(UUID appId, LuisAppV2 luisAppV2, ImportV2AppVersionsOptionalParameter importV2AppOptionalParameter) {
        return importV2AppWithServiceResponseAsync(appId, luisAppV2, importV2AppOptionalParameter).toBlocking().single().body();
    }

    /**
     * Imports a new version into a LUIS application.
     *
     * @param appId The application ID.
     * @param luisAppV2 A LUIS application structure.
     * @param importV2AppOptionalParameter the object representing the optional parameters to be set before calling this 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<String> importV2AppAsync(UUID appId, LuisAppV2 luisAppV2, ImportV2AppVersionsOptionalParameter importV2AppOptionalParameter, final ServiceCallback<String> serviceCallback) {
        return ServiceFuture.fromResponse(importV2AppWithServiceResponseAsync(appId, luisAppV2, importV2AppOptionalParameter), serviceCallback);
    }

    /**
     * Imports a new version into a LUIS application.
     *
     * @param appId The application ID.
     * @param luisAppV2 A LUIS application structure.
     * @param importV2AppOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the String object
     */
    public Observable<String> importV2AppAsync(UUID appId, LuisAppV2 luisAppV2, ImportV2AppVersionsOptionalParameter importV2AppOptionalParameter) {
        return importV2AppWithServiceResponseAsync(appId, luisAppV2, importV2AppOptionalParameter).map(new Func1<ServiceResponse<String>, String>() {
            @Override
            public String call(ServiceResponse<String> response) {
                return response.body();
            }
        });
    }

    /**
     * Imports a new version into a LUIS application.
     *
     * @param appId The application ID.
     * @param luisAppV2 A LUIS application structure.
     * @param importV2AppOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the String object
     */
    public Observable<ServiceResponse<String>> importV2AppWithServiceResponseAsync(UUID appId, LuisAppV2 luisAppV2, ImportV2AppVersionsOptionalParameter importV2AppOptionalParameter) {
        if (this.client.endpoint() == null) {
            throw new IllegalArgumentException("Parameter this.client.endpoint() is required and cannot be null.");
        }
        if (appId == null) {
            throw new IllegalArgumentException("Parameter appId is required and cannot be null.");
        }
        if (luisAppV2 == null) {
            throw new IllegalArgumentException("Parameter luisAppV2 is required and cannot be null.");
        }
        Validator.validate(luisAppV2);
        final String versionId = importV2AppOptionalParameter != null ? importV2AppOptionalParameter.versionId() : null;

        return importV2AppWithServiceResponseAsync(appId, luisAppV2, versionId);
    }

    /**
     * Imports a new version into a LUIS application.
     *
     * @param appId The application ID.
     * @param luisAppV2 A LUIS application structure.
     * @param versionId The new versionId to import. If not specified, the versionId will be read from the imported object.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the String object
     */
    public Observable<ServiceResponse<String>> importV2AppWithServiceResponseAsync(UUID appId, LuisAppV2 luisAppV2, String versionId) {
        if (this.client.endpoint() == null) {
            throw new IllegalArgumentException("Parameter this.client.endpoint() is required and cannot be null.");
        }
        if (appId == null) {
            throw new IllegalArgumentException("Parameter appId is required and cannot be null.");
        }
        if (luisAppV2 == null) {
            throw new IllegalArgumentException("Parameter luisAppV2 is required and cannot be null.");
        }
        Validator.validate(luisAppV2);
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.importV2App(appId, versionId, luisAppV2, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<String>>>() {
                @Override
                public Observable<ServiceResponse<String>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<String> clientResponse = importV2AppDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponse<String> importV2AppDelegate(Response<ResponseBody> response) throws ErrorResponseException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<String, ErrorResponseException>newInstance(this.client.serializerAdapter())
                .register(201, new TypeToken<String>() { }.getType())
                .registerError(ErrorResponseException.class)
                .build(response);
    }

    @Override
    public VersionsImportV2AppParameters importV2App() {
        return new VersionsImportV2AppParameters(this);
    }

    /**
     * Internal class implementing VersionsImportV2AppDefinition.
     */
    class VersionsImportV2AppParameters implements VersionsImportV2AppDefinition {
        private VersionsImpl parent;
        private UUID appId;
        private LuisAppV2 luisAppV2;
        private String versionId;

        /**
         * Constructor.
         * @param parent the parent object.
         */
        VersionsImportV2AppParameters(VersionsImpl parent) {
            this.parent = parent;
        }

        @Override
        public VersionsImportV2AppParameters withAppId(UUID appId) {
            this.appId = appId;
            return this;
        }

        @Override
        public VersionsImportV2AppParameters withLuisAppV2(LuisAppV2 luisAppV2) {
            this.luisAppV2 = luisAppV2;
            return this;
        }

        @Override
        public VersionsImportV2AppParameters withVersionId(String versionId) {
            this.versionId = versionId;
            return this;
        }

        @Override
        public String execute() {
        return importV2AppWithServiceResponseAsync(appId, luisAppV2, versionId).toBlocking().single().body();
    }

        @Override
        public Observable<String> executeAsync() {
            return importV2AppWithServiceResponseAsync(appId, luisAppV2, versionId).map(new Func1<ServiceResponse<String>, String>() {
                @Override
                public String call(ServiceResponse<String> response) {
                    return response.body();
                }
            });
        }
    }


    /**
     * Imports a new version into a LUIS application.
     *
     * @param appId The application ID.
     * @param luisAppLu An LU representing the LUIS application structure.
     * @param importLuFormatOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorResponseException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the String object if successful.
     */
    public String importLuFormat(UUID appId, String luisAppLu, ImportLuFormatVersionsOptionalParameter importLuFormatOptionalParameter) {
        return importLuFormatWithServiceResponseAsync(appId, luisAppLu, importLuFormatOptionalParameter).toBlocking().single().body();
    }

    /**
     * Imports a new version into a LUIS application.
     *
     * @param appId The application ID.
     * @param luisAppLu An LU representing the LUIS application structure.
     * @param importLuFormatOptionalParameter the object representing the optional parameters to be set before calling this 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<String> importLuFormatAsync(UUID appId, String luisAppLu, ImportLuFormatVersionsOptionalParameter importLuFormatOptionalParameter, final ServiceCallback<String> serviceCallback) {
        return ServiceFuture.fromResponse(importLuFormatWithServiceResponseAsync(appId, luisAppLu, importLuFormatOptionalParameter), serviceCallback);
    }

    /**
     * Imports a new version into a LUIS application.
     *
     * @param appId The application ID.
     * @param luisAppLu An LU representing the LUIS application structure.
     * @param importLuFormatOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the String object
     */
    public Observable<String> importLuFormatAsync(UUID appId, String luisAppLu, ImportLuFormatVersionsOptionalParameter importLuFormatOptionalParameter) {
        return importLuFormatWithServiceResponseAsync(appId, luisAppLu, importLuFormatOptionalParameter).map(new Func1<ServiceResponse<String>, String>() {
            @Override
            public String call(ServiceResponse<String> response) {
                return response.body();
            }
        });
    }

    /**
     * Imports a new version into a LUIS application.
     *
     * @param appId The application ID.
     * @param luisAppLu An LU representing the LUIS application structure.
     * @param importLuFormatOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the String object
     */
    public Observable<ServiceResponse<String>> importLuFormatWithServiceResponseAsync(UUID appId, String luisAppLu, ImportLuFormatVersionsOptionalParameter importLuFormatOptionalParameter) {
        if (this.client.endpoint() == null) {
            throw new IllegalArgumentException("Parameter this.client.endpoint() is required and cannot be null.");
        }
        if (appId == null) {
            throw new IllegalArgumentException("Parameter appId is required and cannot be null.");
        }
        if (luisAppLu == null) {
            throw new IllegalArgumentException("Parameter luisAppLu is required and cannot be null.");
        }
        final String versionId = importLuFormatOptionalParameter != null ? importLuFormatOptionalParameter.versionId() : null;

        return importLuFormatWithServiceResponseAsync(appId, luisAppLu, versionId);
    }

    /**
     * Imports a new version into a LUIS application.
     *
     * @param appId The application ID.
     * @param luisAppLu An LU representing the LUIS application structure.
     * @param versionId The new versionId to import. If not specified, the versionId will be read from the imported object.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the String object
     */
    public Observable<ServiceResponse<String>> importLuFormatWithServiceResponseAsync(UUID appId, String luisAppLu, String versionId) {
        if (this.client.endpoint() == null) {
            throw new IllegalArgumentException("Parameter this.client.endpoint() is required and cannot be null.");
        }
        if (appId == null) {
            throw new IllegalArgumentException("Parameter appId is required and cannot be null.");
        }
        if (luisAppLu == null) {
            throw new IllegalArgumentException("Parameter luisAppLu is required and cannot be null.");
        }
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.importLuFormat(appId, versionId, luisAppLu, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<String>>>() {
                @Override
                public Observable<ServiceResponse<String>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<String> clientResponse = importLuFormatDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponse<String> importLuFormatDelegate(Response<ResponseBody> response) throws ErrorResponseException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<String, ErrorResponseException>newInstance(this.client.serializerAdapter())
                .register(201, new TypeToken<String>() { }.getType())
                .registerError(ErrorResponseException.class)
                .build(response);
    }

    @Override
    public VersionsImportLuFormatParameters importLuFormat() {
        return new VersionsImportLuFormatParameters(this);
    }

    /**
     * Internal class implementing VersionsImportLuFormatDefinition.
     */
    class VersionsImportLuFormatParameters implements VersionsImportLuFormatDefinition {
        private VersionsImpl parent;
        private UUID appId;
        private String luisAppLu;
        private String versionId;

        /**
         * Constructor.
         * @param parent the parent object.
         */
        VersionsImportLuFormatParameters(VersionsImpl parent) {
            this.parent = parent;
        }

        @Override
        public VersionsImportLuFormatParameters withAppId(UUID appId) {
            this.appId = appId;
            return this;
        }

        @Override
        public VersionsImportLuFormatParameters withLuisAppLu(String luisAppLu) {
            this.luisAppLu = luisAppLu;
            return this;
        }

        @Override
        public VersionsImportLuFormatParameters withVersionId(String versionId) {
            this.versionId = versionId;
            return this;
        }

        @Override
        public String execute() {
        return importLuFormatWithServiceResponseAsync(appId, luisAppLu, versionId).toBlocking().single().body();
    }

        @Override
        public Observable<String> executeAsync() {
            return importLuFormatWithServiceResponseAsync(appId, luisAppLu, versionId).map(new Func1<ServiceResponse<String>, String>() {
                @Override
                public String call(ServiceResponse<String> response) {
                    return response.body();
                }
            });
        }
    }

    /**
     * Exports a LUIS application to text format.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws CloudException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the InputStream object if successful.
     */
    public InputStream exportLuFormat(UUID appId, String versionId) {
        return exportLuFormatWithServiceResponseAsync(appId, versionId).toBlocking().single().body();
    }

    /**
     * Exports a LUIS application to text format.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @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<InputStream> exportLuFormatAsync(UUID appId, String versionId, final ServiceCallback<InputStream> serviceCallback) {
        return ServiceFuture.fromResponse(exportLuFormatWithServiceResponseAsync(appId, versionId), serviceCallback);
    }

    /**
     * Exports a LUIS application to text format.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the InputStream object
     */
    public Observable<InputStream> exportLuFormatAsync(UUID appId, String versionId) {
        return exportLuFormatWithServiceResponseAsync(appId, versionId).map(new Func1<ServiceResponse<InputStream>, InputStream>() {
            @Override
            public InputStream call(ServiceResponse<InputStream> response) {
                return response.body();
            }
        });
    }

    /**
     * Exports a LUIS application to text format.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the InputStream object
     */
    public Observable<ServiceResponse<InputStream>> exportLuFormatWithServiceResponseAsync(UUID appId, String versionId) {
        if (this.client.endpoint() == null) {
            throw new IllegalArgumentException("Parameter this.client.endpoint() is required and cannot be null.");
        }
        if (appId == null) {
            throw new IllegalArgumentException("Parameter appId is required and cannot be null.");
        }
        if (versionId == null) {
            throw new IllegalArgumentException("Parameter versionId is required and cannot be null.");
        }
        final String format = "lu";
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.exportLuFormat(appId, versionId, format, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<InputStream>>>() {
                @Override
                public Observable<ServiceResponse<InputStream>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<InputStream> clientResponse = exportLuFormatDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponse<InputStream> exportLuFormatDelegate(Response<ResponseBody> response) throws CloudException, IOException, IllegalArgumentException {
        return this.client.restClient().responseBuilderFactory().<InputStream, CloudException>newInstance(this.client.serializerAdapter())
                .register(200, new TypeToken<InputStream>() { }.getType())
                .registerError(CloudException.class)
                .build(response);
    }

}
