/**
 * 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.vision.contentmoderator.implementation;

import com.microsoft.azure.cognitiveservices.vision.contentmoderator.models.AddImageOptionalParameter;
import com.microsoft.azure.cognitiveservices.vision.contentmoderator.models.AddImageUrlInputOptionalParameter;
import com.microsoft.azure.cognitiveservices.vision.contentmoderator.models.AddImageFileInputOptionalParameter;
import retrofit2.Retrofit;
import com.microsoft.azure.cognitiveservices.vision.contentmoderator.ListManagementImages;
import com.google.common.base.Joiner;
import com.google.common.reflect.TypeToken;
import com.microsoft.azure.cognitiveservices.vision.contentmoderator.models.APIErrorException;
import com.microsoft.azure.cognitiveservices.vision.contentmoderator.models.BodyModelModel;
import com.microsoft.azure.cognitiveservices.vision.contentmoderator.models.Image;
import com.microsoft.azure.cognitiveservices.vision.contentmoderator.models.ImageIds;
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 okhttp3.MediaType;
import okhttp3.RequestBody;
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.Query;
import retrofit2.Response;
import rx.functions.Func1;
import rx.Observable;

/**
 * An instance of this class provides access to all the operations defined
 * in ListManagementImages.
 */
public class ListManagementImagesImpl implements ListManagementImages {
    /** The Retrofit service to perform REST calls. */
    private ListManagementImagesService service;
    /** The service client containing this operation class. */
    private ContentModeratorClientImpl client;

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

    /**
     * The interface defining all the services for ListManagementImages to be
     * used by Retrofit to perform actually REST calls.
     */
    interface ListManagementImagesService {
        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.cognitiveservices.vision.contentmoderator.ListManagementImages addImage" })
        @POST("contentmoderator/lists/v1.0/imagelists/{listId}/images")
        Observable<Response<ResponseBody>> addImage(@Path("listId") String listId, @Query("tag") Integer tag, @Query("label") String label, @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.vision.contentmoderator.ListManagementImages deleteAllImages" })
        @HTTP(path = "contentmoderator/lists/v1.0/imagelists/{listId}/images", method = "DELETE", hasBody = true)
        Observable<Response<ResponseBody>> deleteAllImages(@Path("listId") String listId, @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.vision.contentmoderator.ListManagementImages getAllImageIds" })
        @GET("contentmoderator/lists/v1.0/imagelists/{listId}/images")
        Observable<Response<ResponseBody>> getAllImageIds(@Path("listId") String listId, @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.vision.contentmoderator.ListManagementImages deleteImage" })
        @HTTP(path = "contentmoderator/lists/v1.0/imagelists/{listId}/images/{ImageId}", method = "DELETE", hasBody = true)
        Observable<Response<ResponseBody>> deleteImage(@Path("listId") String listId, @Path("ImageId") String imageId, @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.vision.contentmoderator.ListManagementImages addImageUrlInput" })
        @POST("contentmoderator/lists/v1.0/imagelists/{listId}/images")
        Observable<Response<ResponseBody>> addImageUrlInput(@Path("listId") String listId, @Query("tag") Integer tag, @Query("label") String label, @Header("Content-Type") String contentType, @Body BodyModelModel imageUrl, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

        @Headers({ "Content-Type: image/gif", "x-ms-logging-context: com.microsoft.azure.cognitiveservices.vision.contentmoderator.ListManagementImages addImageFileInput" })
        @POST("contentmoderator/lists/v1.0/imagelists/{listId}/images")
        Observable<Response<ResponseBody>> addImageFileInput(@Path("listId") String listId, @Query("tag") Integer tag, @Query("label") String label, @Body RequestBody imageStream, @Header("accept-language") String acceptLanguage, @Header("x-ms-parameterized-host") String parameterizedHost, @Header("User-Agent") String userAgent);

    }


    /**
     * Add an image to the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @param addImageOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws APIErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the Image object if successful.
     */
    public Image addImage(String listId, AddImageOptionalParameter addImageOptionalParameter) {
        return addImageWithServiceResponseAsync(listId, addImageOptionalParameter).toBlocking().single().body();
    }

    /**
     * Add an image to the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @param addImageOptionalParameter 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<Image> addImageAsync(String listId, AddImageOptionalParameter addImageOptionalParameter, final ServiceCallback<Image> serviceCallback) {
        return ServiceFuture.fromResponse(addImageWithServiceResponseAsync(listId, addImageOptionalParameter), serviceCallback);
    }

    /**
     * Add an image to the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @param addImageOptionalParameter 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 Image object
     */
    public Observable<Image> addImageAsync(String listId, AddImageOptionalParameter addImageOptionalParameter) {
        return addImageWithServiceResponseAsync(listId, addImageOptionalParameter).map(new Func1<ServiceResponse<Image>, Image>() {
            @Override
            public Image call(ServiceResponse<Image> response) {
                return response.body();
            }
        });
    }

    /**
     * Add an image to the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @param addImageOptionalParameter 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 Image object
     */
    public Observable<ServiceResponse<Image>> addImageWithServiceResponseAsync(String listId, AddImageOptionalParameter addImageOptionalParameter) {
        if (this.client.baseUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.baseUrl() is required and cannot be null.");
        }
        if (listId == null) {
            throw new IllegalArgumentException("Parameter listId is required and cannot be null.");
        }
        final Integer tag = addImageOptionalParameter != null ? addImageOptionalParameter.tag() : null;
        final String label = addImageOptionalParameter != null ? addImageOptionalParameter.label() : null;

        return addImageWithServiceResponseAsync(listId, tag, label);
    }

    /**
     * Add an image to the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @param tag Tag for the image.
     * @param label The image label.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the Image object
     */
    public Observable<ServiceResponse<Image>> addImageWithServiceResponseAsync(String listId, Integer tag, String label) {
        if (this.client.baseUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.baseUrl() is required and cannot be null.");
        }
        if (listId == null) {
            throw new IllegalArgumentException("Parameter listId is required and cannot be null.");
        }
        String parameterizedHost = Joiner.on(", ").join("{baseUrl}", this.client.baseUrl());
        return service.addImage(listId, tag, label, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<Image>>>() {
                @Override
                public Observable<ServiceResponse<Image>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<Image> clientResponse = addImageDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    @Override
    public ListManagementImagesAddImageParameters addImage() {
        return new ListManagementImagesAddImageParameters(this);
    }

    /**
     * Internal class implementing ListManagementImagesAddImageDefinition.
     */
    class ListManagementImagesAddImageParameters implements ListManagementImagesAddImageDefinition {
        private ListManagementImagesImpl parent;
        private String listId;
        private Integer tag;
        private String label;

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

        @Override
        public ListManagementImagesAddImageParameters withListId(String listId) {
            this.listId = listId;
            return this;
        }

        @Override
        public ListManagementImagesAddImageParameters withTag(Integer tag) {
            this.tag = tag;
            return this;
        }

        @Override
        public ListManagementImagesAddImageParameters withLabel(String label) {
            this.label = label;
            return this;
        }

        @Override
        public Image execute() {
        return addImageWithServiceResponseAsync(listId, tag, label).toBlocking().single().body();
    }

        @Override
        public Observable<Image> executeAsync() {
            return addImageWithServiceResponseAsync(listId, tag, label).map(new Func1<ServiceResponse<Image>, Image>() {
                @Override
                public Image call(ServiceResponse<Image> response) {
                    return response.body();
                }
            });
        }
    }

    /**
     * Deletes all images from the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws APIErrorException 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 deleteAllImages(String listId) {
        return deleteAllImagesWithServiceResponseAsync(listId).toBlocking().single().body();
    }

    /**
     * Deletes all images from the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @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> deleteAllImagesAsync(String listId, final ServiceCallback<String> serviceCallback) {
        return ServiceFuture.fromResponse(deleteAllImagesWithServiceResponseAsync(listId), serviceCallback);
    }

    /**
     * Deletes all images from the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the String object
     */
    public Observable<String> deleteAllImagesAsync(String listId) {
        return deleteAllImagesWithServiceResponseAsync(listId).map(new Func1<ServiceResponse<String>, String>() {
            @Override
            public String call(ServiceResponse<String> response) {
                return response.body();
            }
        });
    }

    /**
     * Deletes all images from the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the String object
     */
    public Observable<ServiceResponse<String>> deleteAllImagesWithServiceResponseAsync(String listId) {
        if (this.client.baseUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.baseUrl() is required and cannot be null.");
        }
        if (listId == null) {
            throw new IllegalArgumentException("Parameter listId is required and cannot be null.");
        }
        String parameterizedHost = Joiner.on(", ").join("{baseUrl}", this.client.baseUrl());
        return service.deleteAllImages(listId, 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 = deleteAllImagesDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Gets all image Ids from the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws APIErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the ImageIds object if successful.
     */
    public ImageIds getAllImageIds(String listId) {
        return getAllImageIdsWithServiceResponseAsync(listId).toBlocking().single().body();
    }

    /**
     * Gets all image Ids from the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @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<ImageIds> getAllImageIdsAsync(String listId, final ServiceCallback<ImageIds> serviceCallback) {
        return ServiceFuture.fromResponse(getAllImageIdsWithServiceResponseAsync(listId), serviceCallback);
    }

    /**
     * Gets all image Ids from the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the ImageIds object
     */
    public Observable<ImageIds> getAllImageIdsAsync(String listId) {
        return getAllImageIdsWithServiceResponseAsync(listId).map(new Func1<ServiceResponse<ImageIds>, ImageIds>() {
            @Override
            public ImageIds call(ServiceResponse<ImageIds> response) {
                return response.body();
            }
        });
    }

    /**
     * Gets all image Ids from the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the ImageIds object
     */
    public Observable<ServiceResponse<ImageIds>> getAllImageIdsWithServiceResponseAsync(String listId) {
        if (this.client.baseUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.baseUrl() is required and cannot be null.");
        }
        if (listId == null) {
            throw new IllegalArgumentException("Parameter listId is required and cannot be null.");
        }
        String parameterizedHost = Joiner.on(", ").join("{baseUrl}", this.client.baseUrl());
        return service.getAllImageIds(listId, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<ImageIds>>>() {
                @Override
                public Observable<ServiceResponse<ImageIds>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<ImageIds> clientResponse = getAllImageIdsDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Deletes an image from the list with list Id and image Id passed.
     *
     * @param listId List Id of the image list.
     * @param imageId Id of the image.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws APIErrorException 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 deleteImage(String listId, String imageId) {
        return deleteImageWithServiceResponseAsync(listId, imageId).toBlocking().single().body();
    }

    /**
     * Deletes an image from the list with list Id and image Id passed.
     *
     * @param listId List Id of the image list.
     * @param imageId Id of the image.
     * @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> deleteImageAsync(String listId, String imageId, final ServiceCallback<String> serviceCallback) {
        return ServiceFuture.fromResponse(deleteImageWithServiceResponseAsync(listId, imageId), serviceCallback);
    }

    /**
     * Deletes an image from the list with list Id and image Id passed.
     *
     * @param listId List Id of the image list.
     * @param imageId Id of the image.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the String object
     */
    public Observable<String> deleteImageAsync(String listId, String imageId) {
        return deleteImageWithServiceResponseAsync(listId, imageId).map(new Func1<ServiceResponse<String>, String>() {
            @Override
            public String call(ServiceResponse<String> response) {
                return response.body();
            }
        });
    }

    /**
     * Deletes an image from the list with list Id and image Id passed.
     *
     * @param listId List Id of the image list.
     * @param imageId Id of the image.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the String object
     */
    public Observable<ServiceResponse<String>> deleteImageWithServiceResponseAsync(String listId, String imageId) {
        if (this.client.baseUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.baseUrl() is required and cannot be null.");
        }
        if (listId == null) {
            throw new IllegalArgumentException("Parameter listId is required and cannot be null.");
        }
        if (imageId == null) {
            throw new IllegalArgumentException("Parameter imageId is required and cannot be null.");
        }
        String parameterizedHost = Joiner.on(", ").join("{baseUrl}", this.client.baseUrl());
        return service.deleteImage(listId, imageId, 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 = deleteImageDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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


    /**
     * Add an image to the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @param contentType The content type.
     * @param imageUrl The image url.
     * @param addImageUrlInputOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws APIErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the Image object if successful.
     */
    public Image addImageUrlInput(String listId, String contentType, BodyModelModel imageUrl, AddImageUrlInputOptionalParameter addImageUrlInputOptionalParameter) {
        return addImageUrlInputWithServiceResponseAsync(listId, contentType, imageUrl, addImageUrlInputOptionalParameter).toBlocking().single().body();
    }

    /**
     * Add an image to the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @param contentType The content type.
     * @param imageUrl The image url.
     * @param addImageUrlInputOptionalParameter 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<Image> addImageUrlInputAsync(String listId, String contentType, BodyModelModel imageUrl, AddImageUrlInputOptionalParameter addImageUrlInputOptionalParameter, final ServiceCallback<Image> serviceCallback) {
        return ServiceFuture.fromResponse(addImageUrlInputWithServiceResponseAsync(listId, contentType, imageUrl, addImageUrlInputOptionalParameter), serviceCallback);
    }

    /**
     * Add an image to the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @param contentType The content type.
     * @param imageUrl The image url.
     * @param addImageUrlInputOptionalParameter 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 Image object
     */
    public Observable<Image> addImageUrlInputAsync(String listId, String contentType, BodyModelModel imageUrl, AddImageUrlInputOptionalParameter addImageUrlInputOptionalParameter) {
        return addImageUrlInputWithServiceResponseAsync(listId, contentType, imageUrl, addImageUrlInputOptionalParameter).map(new Func1<ServiceResponse<Image>, Image>() {
            @Override
            public Image call(ServiceResponse<Image> response) {
                return response.body();
            }
        });
    }

    /**
     * Add an image to the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @param contentType The content type.
     * @param imageUrl The image url.
     * @param addImageUrlInputOptionalParameter 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 Image object
     */
    public Observable<ServiceResponse<Image>> addImageUrlInputWithServiceResponseAsync(String listId, String contentType, BodyModelModel imageUrl, AddImageUrlInputOptionalParameter addImageUrlInputOptionalParameter) {
        if (this.client.baseUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.baseUrl() is required and cannot be null.");
        }
        if (listId == null) {
            throw new IllegalArgumentException("Parameter listId is required and cannot be null.");
        }
        if (contentType == null) {
            throw new IllegalArgumentException("Parameter contentType is required and cannot be null.");
        }
        if (imageUrl == null) {
            throw new IllegalArgumentException("Parameter imageUrl is required and cannot be null.");
        }
        Validator.validate(imageUrl);
        final Integer tag = addImageUrlInputOptionalParameter != null ? addImageUrlInputOptionalParameter.tag() : null;
        final String label = addImageUrlInputOptionalParameter != null ? addImageUrlInputOptionalParameter.label() : null;

        return addImageUrlInputWithServiceResponseAsync(listId, contentType, imageUrl, tag, label);
    }

    /**
     * Add an image to the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @param contentType The content type.
     * @param imageUrl The image url.
     * @param tag Tag for the image.
     * @param label The image label.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the Image object
     */
    public Observable<ServiceResponse<Image>> addImageUrlInputWithServiceResponseAsync(String listId, String contentType, BodyModelModel imageUrl, Integer tag, String label) {
        if (this.client.baseUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.baseUrl() is required and cannot be null.");
        }
        if (listId == null) {
            throw new IllegalArgumentException("Parameter listId is required and cannot be null.");
        }
        if (contentType == null) {
            throw new IllegalArgumentException("Parameter contentType is required and cannot be null.");
        }
        if (imageUrl == null) {
            throw new IllegalArgumentException("Parameter imageUrl is required and cannot be null.");
        }
        Validator.validate(imageUrl);
        String parameterizedHost = Joiner.on(", ").join("{baseUrl}", this.client.baseUrl());
        return service.addImageUrlInput(listId, tag, label, contentType, imageUrl, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<Image>>>() {
                @Override
                public Observable<ServiceResponse<Image>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<Image> clientResponse = addImageUrlInputDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    @Override
    public ListManagementImagesAddImageUrlInputParameters addImageUrlInput() {
        return new ListManagementImagesAddImageUrlInputParameters(this);
    }

    /**
     * Internal class implementing ListManagementImagesAddImageUrlInputDefinition.
     */
    class ListManagementImagesAddImageUrlInputParameters implements ListManagementImagesAddImageUrlInputDefinition {
        private ListManagementImagesImpl parent;
        private String listId;
        private String contentType;
        private BodyModelModel imageUrl;
        private Integer tag;
        private String label;

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

        @Override
        public ListManagementImagesAddImageUrlInputParameters withListId(String listId) {
            this.listId = listId;
            return this;
        }

        @Override
        public ListManagementImagesAddImageUrlInputParameters withContentType(String contentType) {
            this.contentType = contentType;
            return this;
        }

        @Override
        public ListManagementImagesAddImageUrlInputParameters withImageUrl(BodyModelModel imageUrl) {
            this.imageUrl = imageUrl;
            return this;
        }

        @Override
        public ListManagementImagesAddImageUrlInputParameters withTag(Integer tag) {
            this.tag = tag;
            return this;
        }

        @Override
        public ListManagementImagesAddImageUrlInputParameters withLabel(String label) {
            this.label = label;
            return this;
        }

        @Override
        public Image execute() {
        return addImageUrlInputWithServiceResponseAsync(listId, contentType, imageUrl, tag, label).toBlocking().single().body();
    }

        @Override
        public Observable<Image> executeAsync() {
            return addImageUrlInputWithServiceResponseAsync(listId, contentType, imageUrl, tag, label).map(new Func1<ServiceResponse<Image>, Image>() {
                @Override
                public Image call(ServiceResponse<Image> response) {
                    return response.body();
                }
            });
        }
    }


    /**
     * Add an image to the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @param imageStream The image file.
     * @param addImageFileInputOptionalParameter the object representing the optional parameters to be set before calling this API
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws APIErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the Image object if successful.
     */
    public Image addImageFileInput(String listId, byte[] imageStream, AddImageFileInputOptionalParameter addImageFileInputOptionalParameter) {
        return addImageFileInputWithServiceResponseAsync(listId, imageStream, addImageFileInputOptionalParameter).toBlocking().single().body();
    }

    /**
     * Add an image to the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @param imageStream The image file.
     * @param addImageFileInputOptionalParameter 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<Image> addImageFileInputAsync(String listId, byte[] imageStream, AddImageFileInputOptionalParameter addImageFileInputOptionalParameter, final ServiceCallback<Image> serviceCallback) {
        return ServiceFuture.fromResponse(addImageFileInputWithServiceResponseAsync(listId, imageStream, addImageFileInputOptionalParameter), serviceCallback);
    }

    /**
     * Add an image to the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @param imageStream The image file.
     * @param addImageFileInputOptionalParameter 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 Image object
     */
    public Observable<Image> addImageFileInputAsync(String listId, byte[] imageStream, AddImageFileInputOptionalParameter addImageFileInputOptionalParameter) {
        return addImageFileInputWithServiceResponseAsync(listId, imageStream, addImageFileInputOptionalParameter).map(new Func1<ServiceResponse<Image>, Image>() {
            @Override
            public Image call(ServiceResponse<Image> response) {
                return response.body();
            }
        });
    }

    /**
     * Add an image to the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @param imageStream The image file.
     * @param addImageFileInputOptionalParameter 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 Image object
     */
    public Observable<ServiceResponse<Image>> addImageFileInputWithServiceResponseAsync(String listId, byte[] imageStream, AddImageFileInputOptionalParameter addImageFileInputOptionalParameter) {
        if (this.client.baseUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.baseUrl() is required and cannot be null.");
        }
        if (listId == null) {
            throw new IllegalArgumentException("Parameter listId is required and cannot be null.");
        }
        if (imageStream == null) {
            throw new IllegalArgumentException("Parameter imageStream is required and cannot be null.");
        }
        final Integer tag = addImageFileInputOptionalParameter != null ? addImageFileInputOptionalParameter.tag() : null;
        final String label = addImageFileInputOptionalParameter != null ? addImageFileInputOptionalParameter.label() : null;

        return addImageFileInputWithServiceResponseAsync(listId, imageStream, tag, label);
    }

    /**
     * Add an image to the list with list Id equal to list Id passed.
     *
     * @param listId List Id of the image list.
     * @param imageStream The image file.
     * @param tag Tag for the image.
     * @param label The image label.
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the Image object
     */
    public Observable<ServiceResponse<Image>> addImageFileInputWithServiceResponseAsync(String listId, byte[] imageStream, Integer tag, String label) {
        if (this.client.baseUrl() == null) {
            throw new IllegalArgumentException("Parameter this.client.baseUrl() is required and cannot be null.");
        }
        if (listId == null) {
            throw new IllegalArgumentException("Parameter listId is required and cannot be null.");
        }
        if (imageStream == null) {
            throw new IllegalArgumentException("Parameter imageStream is required and cannot be null.");
        }
        String parameterizedHost = Joiner.on(", ").join("{baseUrl}", this.client.baseUrl());
        RequestBody imageStreamConverted = RequestBody.create(MediaType.parse("image/gif"), imageStream);
        return service.addImageFileInput(listId, tag, label, imageStreamConverted, this.client.acceptLanguage(), parameterizedHost, this.client.userAgent())
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<Image>>>() {
                @Override
                public Observable<ServiceResponse<Image>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<Image> clientResponse = addImageFileInputDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    @Override
    public ListManagementImagesAddImageFileInputParameters addImageFileInput() {
        return new ListManagementImagesAddImageFileInputParameters(this);
    }

    /**
     * Internal class implementing ListManagementImagesAddImageFileInputDefinition.
     */
    class ListManagementImagesAddImageFileInputParameters implements ListManagementImagesAddImageFileInputDefinition {
        private ListManagementImagesImpl parent;
        private String listId;
        private byte[] imageStream;
        private Integer tag;
        private String label;

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

        @Override
        public ListManagementImagesAddImageFileInputParameters withListId(String listId) {
            this.listId = listId;
            return this;
        }

        @Override
        public ListManagementImagesAddImageFileInputParameters withImageStream(byte[] imageStream) {
            this.imageStream = imageStream;
            return this;
        }

        @Override
        public ListManagementImagesAddImageFileInputParameters withTag(Integer tag) {
            this.tag = tag;
            return this;
        }

        @Override
        public ListManagementImagesAddImageFileInputParameters withLabel(String label) {
            this.label = label;
            return this;
        }

        @Override
        public Image execute() {
        return addImageFileInputWithServiceResponseAsync(listId, imageStream, tag, label).toBlocking().single().body();
    }

        @Override
        public Observable<Image> executeAsync() {
            return addImageFileInputWithServiceResponseAsync(listId, imageStream, tag, label).map(new Func1<ServiceResponse<Image>, Image>() {
                @Override
                public Image call(ServiceResponse<Image> response) {
                    return response.body();
                }
            });
        }
    }

}
