/**
 * 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.ListPatternsOptionalParameter;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.ListIntentPatternsOptionalParameter;
import retrofit2.Retrofit;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.Patterns;
import com.google.common.base.Joiner;
import com.google.common.reflect.TypeToken;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.ErrorResponseException;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.OperationStatus;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.PatternRuleCreateObject;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.PatternRuleInfo;
import com.microsoft.azure.cognitiveservices.language.luis.authoring.models.PatternRuleUpdateObject;
import com.microsoft.rest.ServiceCallback;
import com.microsoft.rest.ServiceFuture;
import com.microsoft.rest.ServiceResponse;
import com.microsoft.rest.Validator;
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.Response;
import rx.functions.Func1;
import rx.Observable;

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

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

    /**
     * The interface defining all the services for Patterns to be
     * used by Retrofit to perform actually REST calls.
     */
    interface PatternsService {
        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.cognitiveservices.language.luis.authoring.Patterns addPattern" })
        @POST("apps/{appId}/versions/{versionId}/patternrule")
        Observable<Response<ResponseBody>> addPattern(@Path("appId") UUID appId, @Path("versionId") String versionId, @Body PatternRuleCreateObject pattern, @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.Patterns listPatterns" })
        @GET("apps/{appId}/versions/{versionId}/patternrules")
        Observable<Response<ResponseBody>> listPatterns(@Path("appId") UUID appId, @Path("versionId") String versionId, @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.Patterns updatePatterns" })
        @PUT("apps/{appId}/versions/{versionId}/patternrules")
        Observable<Response<ResponseBody>> updatePatterns(@Path("appId") UUID appId, @Path("versionId") String versionId, @Body List<PatternRuleUpdateObject> patterns, @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.Patterns batchAddPatterns" })
        @POST("apps/{appId}/versions/{versionId}/patternrules")
        Observable<Response<ResponseBody>> batchAddPatterns(@Path("appId") UUID appId, @Path("versionId") String versionId, @Body List<PatternRuleCreateObject> patterns, @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.Patterns deletePatterns" })
        @HTTP(path = "apps/{appId}/versions/{versionId}/patternrules", method = "DELETE", hasBody = true)
        Observable<Response<ResponseBody>> deletePatterns(@Path("appId") UUID appId, @Path("versionId") String versionId, @Body List<UUID> patternIds, @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.Patterns updatePattern" })
        @PUT("apps/{appId}/versions/{versionId}/patternrules/{patternId}")
        Observable<Response<ResponseBody>> updatePattern(@Path("appId") UUID appId, @Path("versionId") String versionId, @Path("patternId") UUID patternId, @Body PatternRuleUpdateObject pattern, @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.Patterns deletePattern" })
        @HTTP(path = "apps/{appId}/versions/{versionId}/patternrules/{patternId}", method = "DELETE", hasBody = true)
        Observable<Response<ResponseBody>> deletePattern(@Path("appId") UUID appId, @Path("versionId") String versionId, @Path("patternId") UUID patternId, @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.Patterns listIntentPatterns" })
        @GET("apps/{appId}/versions/{versionId}/intents/{intentId}/patternrules")
        Observable<Response<ResponseBody>> listIntentPatterns(@Path("appId") UUID appId, @Path("versionId") String versionId, @Path("intentId") UUID intentId, @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);

    }

    /**
     * Adds a pattern to a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param pattern The input pattern.
     * @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 PatternRuleInfo object if successful.
     */
    public PatternRuleInfo addPattern(UUID appId, String versionId, PatternRuleCreateObject pattern) {
        return addPatternWithServiceResponseAsync(appId, versionId, pattern).toBlocking().single().body();
    }

    /**
     * Adds a pattern to a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param pattern The input pattern.
     * @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<PatternRuleInfo> addPatternAsync(UUID appId, String versionId, PatternRuleCreateObject pattern, final ServiceCallback<PatternRuleInfo> serviceCallback) {
        return ServiceFuture.fromResponse(addPatternWithServiceResponseAsync(appId, versionId, pattern), serviceCallback);
    }

    /**
     * Adds a pattern to a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param pattern The input pattern.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PatternRuleInfo object
     */
    public Observable<PatternRuleInfo> addPatternAsync(UUID appId, String versionId, PatternRuleCreateObject pattern) {
        return addPatternWithServiceResponseAsync(appId, versionId, pattern).map(new Func1<ServiceResponse<PatternRuleInfo>, PatternRuleInfo>() {
            @Override
            public PatternRuleInfo call(ServiceResponse<PatternRuleInfo> response) {
                return response.body();
            }
        });
    }

    /**
     * Adds a pattern to a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param pattern The input pattern.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PatternRuleInfo object
     */
    public Observable<ServiceResponse<PatternRuleInfo>> addPatternWithServiceResponseAsync(UUID appId, String versionId, PatternRuleCreateObject pattern) {
        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 (pattern == null) {
            throw new IllegalArgumentException("Parameter pattern is required and cannot be null.");
        }
        Validator.validate(pattern);
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.addPattern(appId, versionId, pattern, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<PatternRuleInfo>>>() {
                @Override
                public Observable<ServiceResponse<PatternRuleInfo>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<PatternRuleInfo> clientResponse = addPatternDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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


    /**
     * Gets patterns in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param listPatternsOptionalParameter 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;PatternRuleInfo&gt; object if successful.
     */
    public List<PatternRuleInfo> listPatterns(UUID appId, String versionId, ListPatternsOptionalParameter listPatternsOptionalParameter) {
        return listPatternsWithServiceResponseAsync(appId, versionId, listPatternsOptionalParameter).toBlocking().single().body();
    }

    /**
     * Gets patterns in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param listPatternsOptionalParameter 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<PatternRuleInfo>> listPatternsAsync(UUID appId, String versionId, ListPatternsOptionalParameter listPatternsOptionalParameter, final ServiceCallback<List<PatternRuleInfo>> serviceCallback) {
        return ServiceFuture.fromResponse(listPatternsWithServiceResponseAsync(appId, versionId, listPatternsOptionalParameter), serviceCallback);
    }

    /**
     * Gets patterns in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param listPatternsOptionalParameter 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;PatternRuleInfo&gt; object
     */
    public Observable<List<PatternRuleInfo>> listPatternsAsync(UUID appId, String versionId, ListPatternsOptionalParameter listPatternsOptionalParameter) {
        return listPatternsWithServiceResponseAsync(appId, versionId, listPatternsOptionalParameter).map(new Func1<ServiceResponse<List<PatternRuleInfo>>, List<PatternRuleInfo>>() {
            @Override
            public List<PatternRuleInfo> call(ServiceResponse<List<PatternRuleInfo>> response) {
                return response.body();
            }
        });
    }

    /**
     * Gets patterns in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param listPatternsOptionalParameter 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;PatternRuleInfo&gt; object
     */
    public Observable<ServiceResponse<List<PatternRuleInfo>>> listPatternsWithServiceResponseAsync(UUID appId, String versionId, ListPatternsOptionalParameter listPatternsOptionalParameter) {
        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 Integer skip = listPatternsOptionalParameter != null ? listPatternsOptionalParameter.skip() : null;
        final Integer take = listPatternsOptionalParameter != null ? listPatternsOptionalParameter.take() : null;

        return listPatternsWithServiceResponseAsync(appId, versionId, skip, take);
    }

    /**
     * Gets patterns in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version 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;PatternRuleInfo&gt; object
     */
    public Observable<ServiceResponse<List<PatternRuleInfo>>> listPatternsWithServiceResponseAsync(UUID appId, String versionId, 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.");
        }
        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.listPatterns(appId, versionId, skip, take, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<List<PatternRuleInfo>>>>() {
                @Override
                public Observable<ServiceResponse<List<PatternRuleInfo>>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<List<PatternRuleInfo>> clientResponse = listPatternsDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    @Override
    public PatternsListPatternsParameters listPatterns() {
        return new PatternsListPatternsParameters(this);
    }

    /**
     * Internal class implementing PatternsListPatternsDefinition.
     */
    class PatternsListPatternsParameters implements PatternsListPatternsDefinition {
        private PatternsImpl parent;
        private UUID appId;
        private String versionId;
        private Integer skip;
        private Integer take;

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

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

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

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

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

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

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

    /**
     * Updates patterns in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patterns An array represents the patterns.
     * @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;PatternRuleInfo&gt; object if successful.
     */
    public List<PatternRuleInfo> updatePatterns(UUID appId, String versionId, List<PatternRuleUpdateObject> patterns) {
        return updatePatternsWithServiceResponseAsync(appId, versionId, patterns).toBlocking().single().body();
    }

    /**
     * Updates patterns in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patterns An array represents the patterns.
     * @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<PatternRuleInfo>> updatePatternsAsync(UUID appId, String versionId, List<PatternRuleUpdateObject> patterns, final ServiceCallback<List<PatternRuleInfo>> serviceCallback) {
        return ServiceFuture.fromResponse(updatePatternsWithServiceResponseAsync(appId, versionId, patterns), serviceCallback);
    }

    /**
     * Updates patterns in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patterns An array represents the patterns.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the List&lt;PatternRuleInfo&gt; object
     */
    public Observable<List<PatternRuleInfo>> updatePatternsAsync(UUID appId, String versionId, List<PatternRuleUpdateObject> patterns) {
        return updatePatternsWithServiceResponseAsync(appId, versionId, patterns).map(new Func1<ServiceResponse<List<PatternRuleInfo>>, List<PatternRuleInfo>>() {
            @Override
            public List<PatternRuleInfo> call(ServiceResponse<List<PatternRuleInfo>> response) {
                return response.body();
            }
        });
    }

    /**
     * Updates patterns in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patterns An array represents the patterns.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the List&lt;PatternRuleInfo&gt; object
     */
    public Observable<ServiceResponse<List<PatternRuleInfo>>> updatePatternsWithServiceResponseAsync(UUID appId, String versionId, List<PatternRuleUpdateObject> patterns) {
        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 (patterns == null) {
            throw new IllegalArgumentException("Parameter patterns is required and cannot be null.");
        }
        Validator.validate(patterns);
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.updatePatterns(appId, versionId, patterns, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<List<PatternRuleInfo>>>>() {
                @Override
                public Observable<ServiceResponse<List<PatternRuleInfo>>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<List<PatternRuleInfo>> clientResponse = updatePatternsDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Adds a batch of patterns in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patterns A JSON array containing patterns.
     * @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;PatternRuleInfo&gt; object if successful.
     */
    public List<PatternRuleInfo> batchAddPatterns(UUID appId, String versionId, List<PatternRuleCreateObject> patterns) {
        return batchAddPatternsWithServiceResponseAsync(appId, versionId, patterns).toBlocking().single().body();
    }

    /**
     * Adds a batch of patterns in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patterns A JSON array containing patterns.
     * @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<PatternRuleInfo>> batchAddPatternsAsync(UUID appId, String versionId, List<PatternRuleCreateObject> patterns, final ServiceCallback<List<PatternRuleInfo>> serviceCallback) {
        return ServiceFuture.fromResponse(batchAddPatternsWithServiceResponseAsync(appId, versionId, patterns), serviceCallback);
    }

    /**
     * Adds a batch of patterns in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patterns A JSON array containing patterns.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the List&lt;PatternRuleInfo&gt; object
     */
    public Observable<List<PatternRuleInfo>> batchAddPatternsAsync(UUID appId, String versionId, List<PatternRuleCreateObject> patterns) {
        return batchAddPatternsWithServiceResponseAsync(appId, versionId, patterns).map(new Func1<ServiceResponse<List<PatternRuleInfo>>, List<PatternRuleInfo>>() {
            @Override
            public List<PatternRuleInfo> call(ServiceResponse<List<PatternRuleInfo>> response) {
                return response.body();
            }
        });
    }

    /**
     * Adds a batch of patterns in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patterns A JSON array containing patterns.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the List&lt;PatternRuleInfo&gt; object
     */
    public Observable<ServiceResponse<List<PatternRuleInfo>>> batchAddPatternsWithServiceResponseAsync(UUID appId, String versionId, List<PatternRuleCreateObject> patterns) {
        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 (patterns == null) {
            throw new IllegalArgumentException("Parameter patterns is required and cannot be null.");
        }
        Validator.validate(patterns);
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.batchAddPatterns(appId, versionId, patterns, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<List<PatternRuleInfo>>>>() {
                @Override
                public Observable<ServiceResponse<List<PatternRuleInfo>>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<List<PatternRuleInfo>> clientResponse = batchAddPatternsDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Deletes a list of patterns in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patternIds The patterns IDs.
     * @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 deletePatterns(UUID appId, String versionId, List<UUID> patternIds) {
        return deletePatternsWithServiceResponseAsync(appId, versionId, patternIds).toBlocking().single().body();
    }

    /**
     * Deletes a list of patterns in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patternIds The patterns IDs.
     * @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> deletePatternsAsync(UUID appId, String versionId, List<UUID> patternIds, final ServiceCallback<OperationStatus> serviceCallback) {
        return ServiceFuture.fromResponse(deletePatternsWithServiceResponseAsync(appId, versionId, patternIds), serviceCallback);
    }

    /**
     * Deletes a list of patterns in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patternIds The patterns IDs.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the OperationStatus object
     */
    public Observable<OperationStatus> deletePatternsAsync(UUID appId, String versionId, List<UUID> patternIds) {
        return deletePatternsWithServiceResponseAsync(appId, versionId, patternIds).map(new Func1<ServiceResponse<OperationStatus>, OperationStatus>() {
            @Override
            public OperationStatus call(ServiceResponse<OperationStatus> response) {
                return response.body();
            }
        });
    }

    /**
     * Deletes a list of patterns in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patternIds The patterns IDs.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the OperationStatus object
     */
    public Observable<ServiceResponse<OperationStatus>> deletePatternsWithServiceResponseAsync(UUID appId, String versionId, List<UUID> patternIds) {
        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 (patternIds == null) {
            throw new IllegalArgumentException("Parameter patternIds is required and cannot be null.");
        }
        Validator.validate(patternIds);
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.deletePatterns(appId, versionId, patternIds, 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 = deletePatternsDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponse<OperationStatus> deletePatternsDelegate(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);
    }

    /**
     * Updates a pattern in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patternId The pattern ID.
     * @param pattern An object representing a pattern.
     * @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 PatternRuleInfo object if successful.
     */
    public PatternRuleInfo updatePattern(UUID appId, String versionId, UUID patternId, PatternRuleUpdateObject pattern) {
        return updatePatternWithServiceResponseAsync(appId, versionId, patternId, pattern).toBlocking().single().body();
    }

    /**
     * Updates a pattern in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patternId The pattern ID.
     * @param pattern An object representing a pattern.
     * @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<PatternRuleInfo> updatePatternAsync(UUID appId, String versionId, UUID patternId, PatternRuleUpdateObject pattern, final ServiceCallback<PatternRuleInfo> serviceCallback) {
        return ServiceFuture.fromResponse(updatePatternWithServiceResponseAsync(appId, versionId, patternId, pattern), serviceCallback);
    }

    /**
     * Updates a pattern in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patternId The pattern ID.
     * @param pattern An object representing a pattern.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PatternRuleInfo object
     */
    public Observable<PatternRuleInfo> updatePatternAsync(UUID appId, String versionId, UUID patternId, PatternRuleUpdateObject pattern) {
        return updatePatternWithServiceResponseAsync(appId, versionId, patternId, pattern).map(new Func1<ServiceResponse<PatternRuleInfo>, PatternRuleInfo>() {
            @Override
            public PatternRuleInfo call(ServiceResponse<PatternRuleInfo> response) {
                return response.body();
            }
        });
    }

    /**
     * Updates a pattern in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patternId The pattern ID.
     * @param pattern An object representing a pattern.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the PatternRuleInfo object
     */
    public Observable<ServiceResponse<PatternRuleInfo>> updatePatternWithServiceResponseAsync(UUID appId, String versionId, UUID patternId, PatternRuleUpdateObject pattern) {
        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 (patternId == null) {
            throw new IllegalArgumentException("Parameter patternId is required and cannot be null.");
        }
        if (pattern == null) {
            throw new IllegalArgumentException("Parameter pattern is required and cannot be null.");
        }
        Validator.validate(pattern);
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.updatePattern(appId, versionId, patternId, pattern, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<PatternRuleInfo>>>() {
                @Override
                public Observable<ServiceResponse<PatternRuleInfo>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<PatternRuleInfo> clientResponse = updatePatternDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Deletes the pattern with the specified ID from a version of the application..
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patternId The pattern 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 deletePattern(UUID appId, String versionId, UUID patternId) {
        return deletePatternWithServiceResponseAsync(appId, versionId, patternId).toBlocking().single().body();
    }

    /**
     * Deletes the pattern with the specified ID from a version of the application..
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patternId The pattern 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> deletePatternAsync(UUID appId, String versionId, UUID patternId, final ServiceCallback<OperationStatus> serviceCallback) {
        return ServiceFuture.fromResponse(deletePatternWithServiceResponseAsync(appId, versionId, patternId), serviceCallback);
    }

    /**
     * Deletes the pattern with the specified ID from a version of the application..
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patternId The pattern ID.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the OperationStatus object
     */
    public Observable<OperationStatus> deletePatternAsync(UUID appId, String versionId, UUID patternId) {
        return deletePatternWithServiceResponseAsync(appId, versionId, patternId).map(new Func1<ServiceResponse<OperationStatus>, OperationStatus>() {
            @Override
            public OperationStatus call(ServiceResponse<OperationStatus> response) {
                return response.body();
            }
        });
    }

    /**
     * Deletes the pattern with the specified ID from a version of the application..
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param patternId The pattern ID.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the OperationStatus object
     */
    public Observable<ServiceResponse<OperationStatus>> deletePatternWithServiceResponseAsync(UUID appId, String versionId, UUID patternId) {
        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 (patternId == null) {
            throw new IllegalArgumentException("Parameter patternId is required and cannot be null.");
        }
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.deletePattern(appId, versionId, patternId, 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 = deletePatternDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

    private ServiceResponse<OperationStatus> deletePatternDelegate(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);
    }


    /**
     * Returns patterns for the specific intent in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param intentId The intent classifier ID.
     * @param listIntentPatternsOptionalParameter 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;PatternRuleInfo&gt; object if successful.
     */
    public List<PatternRuleInfo> listIntentPatterns(UUID appId, String versionId, UUID intentId, ListIntentPatternsOptionalParameter listIntentPatternsOptionalParameter) {
        return listIntentPatternsWithServiceResponseAsync(appId, versionId, intentId, listIntentPatternsOptionalParameter).toBlocking().single().body();
    }

    /**
     * Returns patterns for the specific intent in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param intentId The intent classifier ID.
     * @param listIntentPatternsOptionalParameter 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<PatternRuleInfo>> listIntentPatternsAsync(UUID appId, String versionId, UUID intentId, ListIntentPatternsOptionalParameter listIntentPatternsOptionalParameter, final ServiceCallback<List<PatternRuleInfo>> serviceCallback) {
        return ServiceFuture.fromResponse(listIntentPatternsWithServiceResponseAsync(appId, versionId, intentId, listIntentPatternsOptionalParameter), serviceCallback);
    }

    /**
     * Returns patterns for the specific intent in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param intentId The intent classifier ID.
     * @param listIntentPatternsOptionalParameter 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;PatternRuleInfo&gt; object
     */
    public Observable<List<PatternRuleInfo>> listIntentPatternsAsync(UUID appId, String versionId, UUID intentId, ListIntentPatternsOptionalParameter listIntentPatternsOptionalParameter) {
        return listIntentPatternsWithServiceResponseAsync(appId, versionId, intentId, listIntentPatternsOptionalParameter).map(new Func1<ServiceResponse<List<PatternRuleInfo>>, List<PatternRuleInfo>>() {
            @Override
            public List<PatternRuleInfo> call(ServiceResponse<List<PatternRuleInfo>> response) {
                return response.body();
            }
        });
    }

    /**
     * Returns patterns for the specific intent in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param intentId The intent classifier ID.
     * @param listIntentPatternsOptionalParameter 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;PatternRuleInfo&gt; object
     */
    public Observable<ServiceResponse<List<PatternRuleInfo>>> listIntentPatternsWithServiceResponseAsync(UUID appId, String versionId, UUID intentId, ListIntentPatternsOptionalParameter listIntentPatternsOptionalParameter) {
        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 (intentId == null) {
            throw new IllegalArgumentException("Parameter intentId is required and cannot be null.");
        }
        final Integer skip = listIntentPatternsOptionalParameter != null ? listIntentPatternsOptionalParameter.skip() : null;
        final Integer take = listIntentPatternsOptionalParameter != null ? listIntentPatternsOptionalParameter.take() : null;

        return listIntentPatternsWithServiceResponseAsync(appId, versionId, intentId, skip, take);
    }

    /**
     * Returns patterns for the specific intent in a version of the application.
     *
     * @param appId The application ID.
     * @param versionId The version ID.
     * @param intentId The intent classifier 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;PatternRuleInfo&gt; object
     */
    public Observable<ServiceResponse<List<PatternRuleInfo>>> listIntentPatternsWithServiceResponseAsync(UUID appId, String versionId, UUID intentId, 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.");
        }
        if (versionId == null) {
            throw new IllegalArgumentException("Parameter versionId is required and cannot be null.");
        }
        if (intentId == null) {
            throw new IllegalArgumentException("Parameter intentId is required and cannot be null.");
        }
        String parameterizedHost = Joiner.on(", ").join("{Endpoint}", this.client.endpoint());
        return service.listIntentPatterns(appId, versionId, intentId, skip, take, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<List<PatternRuleInfo>>>>() {
                @Override
                public Observable<ServiceResponse<List<PatternRuleInfo>>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<List<PatternRuleInfo>> clientResponse = listIntentPatternsDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    @Override
    public PatternsListIntentPatternsParameters listIntentPatterns() {
        return new PatternsListIntentPatternsParameters(this);
    }

    /**
     * Internal class implementing PatternsListIntentPatternsDefinition.
     */
    class PatternsListIntentPatternsParameters implements PatternsListIntentPatternsDefinition {
        private PatternsImpl parent;
        private UUID appId;
        private String versionId;
        private UUID intentId;
        private Integer skip;
        private Integer take;

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

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

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

        @Override
        public PatternsListIntentPatternsParameters withIntentId(UUID intentId) {
            this.intentId = intentId;
            return this;
        }

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

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

        @Override
        public List<PatternRuleInfo> execute() {
        return listIntentPatternsWithServiceResponseAsync(appId, versionId, intentId, skip, take).toBlocking().single().body();
    }

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

}
