/**
 * 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.
 * Changes may cause incorrect behavior and will be lost if the code is
 * regenerated.
 */

package fixtures.bodydate.implementation;

import retrofit2.Retrofit;
import fixtures.bodydate.Dates;
import com.google.common.reflect.TypeToken;
import com.microsoft.rest.ServiceCallback;
import com.microsoft.rest.ServiceFuture;
import com.microsoft.rest.ServiceResponse;
import fixtures.bodydate.models.ErrorException;
import java.io.IOException;
import okhttp3.ResponseBody;
import org.joda.time.LocalDate;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.Headers;
import retrofit2.http.PUT;
import retrofit2.Response;
import rx.functions.Func1;
import rx.Observable;

/**
 * An instance of this class provides access to all the operations defined
 * in Dates.
 */
public class DatesImpl implements Dates {
    /** The Retrofit service to perform REST calls. */
    private DatesService service;
    /** The service client containing this operation class. */
    private AutoRestDateTestServiceImpl client;

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

    /**
     * The interface defining all the services for Dates to be
     * used by Retrofit to perform actually REST calls.
     */
    interface DatesService {
        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: fixtures.bodydate.Dates getNull" })
        @GET("date/null")
        Observable<Response<ResponseBody>> getNull();

        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: fixtures.bodydate.Dates getInvalidDate" })
        @GET("date/invaliddate")
        Observable<Response<ResponseBody>> getInvalidDate();

        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: fixtures.bodydate.Dates getOverflowDate" })
        @GET("date/overflowdate")
        Observable<Response<ResponseBody>> getOverflowDate();

        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: fixtures.bodydate.Dates getUnderflowDate" })
        @GET("date/underflowdate")
        Observable<Response<ResponseBody>> getUnderflowDate();

        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: fixtures.bodydate.Dates putMaxDate" })
        @PUT("date/max")
        Observable<Response<ResponseBody>> putMaxDate(@Body LocalDate dateBody);

        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: fixtures.bodydate.Dates getMaxDate" })
        @GET("date/max")
        Observable<Response<ResponseBody>> getMaxDate();

        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: fixtures.bodydate.Dates putMinDate" })
        @PUT("date/min")
        Observable<Response<ResponseBody>> putMinDate(@Body LocalDate dateBody);

        @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: fixtures.bodydate.Dates getMinDate" })
        @GET("date/min")
        Observable<Response<ResponseBody>> getMinDate();

    }

    /**
     * Get null date value.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the LocalDate object if successful.
     */
    public LocalDate getNull() {
        return getNullWithServiceResponseAsync().toBlocking().single().body();
    }

    /**
     * Get null date value.
     *
     * @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<LocalDate> getNullAsync(final ServiceCallback<LocalDate> serviceCallback) {
        return ServiceFuture.fromResponse(getNullWithServiceResponseAsync(), serviceCallback);
    }

    /**
     * Get null date value.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the LocalDate object
     */
    public Observable<LocalDate> getNullAsync() {
        return getNullWithServiceResponseAsync().map(new Func1<ServiceResponse<LocalDate>, LocalDate>() {
            @Override
            public LocalDate call(ServiceResponse<LocalDate> response) {
                return response.body();
            }
        });
    }

    /**
     * Get null date value.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the LocalDate object
     */
    public Observable<ServiceResponse<LocalDate>> getNullWithServiceResponseAsync() {
        return service.getNull()
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<LocalDate>>>() {
                @Override
                public Observable<ServiceResponse<LocalDate>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<LocalDate> clientResponse = getNullDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Get invalid date value.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the LocalDate object if successful.
     */
    public LocalDate getInvalidDate() {
        return getInvalidDateWithServiceResponseAsync().toBlocking().single().body();
    }

    /**
     * Get invalid date value.
     *
     * @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<LocalDate> getInvalidDateAsync(final ServiceCallback<LocalDate> serviceCallback) {
        return ServiceFuture.fromResponse(getInvalidDateWithServiceResponseAsync(), serviceCallback);
    }

    /**
     * Get invalid date value.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the LocalDate object
     */
    public Observable<LocalDate> getInvalidDateAsync() {
        return getInvalidDateWithServiceResponseAsync().map(new Func1<ServiceResponse<LocalDate>, LocalDate>() {
            @Override
            public LocalDate call(ServiceResponse<LocalDate> response) {
                return response.body();
            }
        });
    }

    /**
     * Get invalid date value.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the LocalDate object
     */
    public Observable<ServiceResponse<LocalDate>> getInvalidDateWithServiceResponseAsync() {
        return service.getInvalidDate()
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<LocalDate>>>() {
                @Override
                public Observable<ServiceResponse<LocalDate>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<LocalDate> clientResponse = getInvalidDateDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Get overflow date value.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the LocalDate object if successful.
     */
    public LocalDate getOverflowDate() {
        return getOverflowDateWithServiceResponseAsync().toBlocking().single().body();
    }

    /**
     * Get overflow date value.
     *
     * @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<LocalDate> getOverflowDateAsync(final ServiceCallback<LocalDate> serviceCallback) {
        return ServiceFuture.fromResponse(getOverflowDateWithServiceResponseAsync(), serviceCallback);
    }

    /**
     * Get overflow date value.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the LocalDate object
     */
    public Observable<LocalDate> getOverflowDateAsync() {
        return getOverflowDateWithServiceResponseAsync().map(new Func1<ServiceResponse<LocalDate>, LocalDate>() {
            @Override
            public LocalDate call(ServiceResponse<LocalDate> response) {
                return response.body();
            }
        });
    }

    /**
     * Get overflow date value.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the LocalDate object
     */
    public Observable<ServiceResponse<LocalDate>> getOverflowDateWithServiceResponseAsync() {
        return service.getOverflowDate()
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<LocalDate>>>() {
                @Override
                public Observable<ServiceResponse<LocalDate>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<LocalDate> clientResponse = getOverflowDateDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Get underflow date value.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the LocalDate object if successful.
     */
    public LocalDate getUnderflowDate() {
        return getUnderflowDateWithServiceResponseAsync().toBlocking().single().body();
    }

    /**
     * Get underflow date value.
     *
     * @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<LocalDate> getUnderflowDateAsync(final ServiceCallback<LocalDate> serviceCallback) {
        return ServiceFuture.fromResponse(getUnderflowDateWithServiceResponseAsync(), serviceCallback);
    }

    /**
     * Get underflow date value.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the LocalDate object
     */
    public Observable<LocalDate> getUnderflowDateAsync() {
        return getUnderflowDateWithServiceResponseAsync().map(new Func1<ServiceResponse<LocalDate>, LocalDate>() {
            @Override
            public LocalDate call(ServiceResponse<LocalDate> response) {
                return response.body();
            }
        });
    }

    /**
     * Get underflow date value.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the LocalDate object
     */
    public Observable<ServiceResponse<LocalDate>> getUnderflowDateWithServiceResponseAsync() {
        return service.getUnderflowDate()
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<LocalDate>>>() {
                @Override
                public Observable<ServiceResponse<LocalDate>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<LocalDate> clientResponse = getUnderflowDateDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Put max date value 9999-12-31.
     *
     * @param dateBody the LocalDate value
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void putMaxDate(LocalDate dateBody) {
        putMaxDateWithServiceResponseAsync(dateBody).toBlocking().single().body();
    }

    /**
     * Put max date value 9999-12-31.
     *
     * @param dateBody the LocalDate value
     * @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<Void> putMaxDateAsync(LocalDate dateBody, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromResponse(putMaxDateWithServiceResponseAsync(dateBody), serviceCallback);
    }

    /**
     * Put max date value 9999-12-31.
     *
     * @param dateBody the LocalDate value
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponse} object if successful.
     */
    public Observable<Void> putMaxDateAsync(LocalDate dateBody) {
        return putMaxDateWithServiceResponseAsync(dateBody).map(new Func1<ServiceResponse<Void>, Void>() {
            @Override
            public Void call(ServiceResponse<Void> response) {
                return response.body();
            }
        });
    }

    /**
     * Put max date value 9999-12-31.
     *
     * @param dateBody the LocalDate value
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponse} object if successful.
     */
    public Observable<ServiceResponse<Void>> putMaxDateWithServiceResponseAsync(LocalDate dateBody) {
        if (dateBody == null) {
            throw new IllegalArgumentException("Parameter dateBody is required and cannot be null.");
        }
        return service.putMaxDate(dateBody)
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<Void>>>() {
                @Override
                public Observable<ServiceResponse<Void>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<Void> clientResponse = putMaxDateDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Get max date value 9999-12-31.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the LocalDate object if successful.
     */
    public LocalDate getMaxDate() {
        return getMaxDateWithServiceResponseAsync().toBlocking().single().body();
    }

    /**
     * Get max date value 9999-12-31.
     *
     * @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<LocalDate> getMaxDateAsync(final ServiceCallback<LocalDate> serviceCallback) {
        return ServiceFuture.fromResponse(getMaxDateWithServiceResponseAsync(), serviceCallback);
    }

    /**
     * Get max date value 9999-12-31.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the LocalDate object
     */
    public Observable<LocalDate> getMaxDateAsync() {
        return getMaxDateWithServiceResponseAsync().map(new Func1<ServiceResponse<LocalDate>, LocalDate>() {
            @Override
            public LocalDate call(ServiceResponse<LocalDate> response) {
                return response.body();
            }
        });
    }

    /**
     * Get max date value 9999-12-31.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the LocalDate object
     */
    public Observable<ServiceResponse<LocalDate>> getMaxDateWithServiceResponseAsync() {
        return service.getMaxDate()
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<LocalDate>>>() {
                @Override
                public Observable<ServiceResponse<LocalDate>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<LocalDate> clientResponse = getMaxDateDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Put min date value 0000-01-01.
     *
     * @param dateBody the LocalDate value
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     */
    public void putMinDate(LocalDate dateBody) {
        putMinDateWithServiceResponseAsync(dateBody).toBlocking().single().body();
    }

    /**
     * Put min date value 0000-01-01.
     *
     * @param dateBody the LocalDate value
     * @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<Void> putMinDateAsync(LocalDate dateBody, final ServiceCallback<Void> serviceCallback) {
        return ServiceFuture.fromResponse(putMinDateWithServiceResponseAsync(dateBody), serviceCallback);
    }

    /**
     * Put min date value 0000-01-01.
     *
     * @param dateBody the LocalDate value
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponse} object if successful.
     */
    public Observable<Void> putMinDateAsync(LocalDate dateBody) {
        return putMinDateWithServiceResponseAsync(dateBody).map(new Func1<ServiceResponse<Void>, Void>() {
            @Override
            public Void call(ServiceResponse<Void> response) {
                return response.body();
            }
        });
    }

    /**
     * Put min date value 0000-01-01.
     *
     * @param dateBody the LocalDate value
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the {@link ServiceResponse} object if successful.
     */
    public Observable<ServiceResponse<Void>> putMinDateWithServiceResponseAsync(LocalDate dateBody) {
        if (dateBody == null) {
            throw new IllegalArgumentException("Parameter dateBody is required and cannot be null.");
        }
        return service.putMinDate(dateBody)
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<Void>>>() {
                @Override
                public Observable<ServiceResponse<Void>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<Void> clientResponse = putMinDateDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

    /**
     * Get min date value 0000-01-01.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @throws ErrorException thrown if the request is rejected by server
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent
     * @return the LocalDate object if successful.
     */
    public LocalDate getMinDate() {
        return getMinDateWithServiceResponseAsync().toBlocking().single().body();
    }

    /**
     * Get min date value 0000-01-01.
     *
     * @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<LocalDate> getMinDateAsync(final ServiceCallback<LocalDate> serviceCallback) {
        return ServiceFuture.fromResponse(getMinDateWithServiceResponseAsync(), serviceCallback);
    }

    /**
     * Get min date value 0000-01-01.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the LocalDate object
     */
    public Observable<LocalDate> getMinDateAsync() {
        return getMinDateWithServiceResponseAsync().map(new Func1<ServiceResponse<LocalDate>, LocalDate>() {
            @Override
            public LocalDate call(ServiceResponse<LocalDate> response) {
                return response.body();
            }
        });
    }

    /**
     * Get min date value 0000-01-01.
     *
     * @throws IllegalArgumentException thrown if parameters fail the validation
     * @return the observable to the LocalDate object
     */
    public Observable<ServiceResponse<LocalDate>> getMinDateWithServiceResponseAsync() {
        return service.getMinDate()
            .flatMap(new Func1<Response<ResponseBody>, Observable<ServiceResponse<LocalDate>>>() {
                @Override
                public Observable<ServiceResponse<LocalDate>> call(Response<ResponseBody> response) {
                    try {
                        ServiceResponse<LocalDate> clientResponse = getMinDateDelegate(response);
                        return Observable.just(clientResponse);
                    } catch (Throwable t) {
                        return Observable.error(t);
                    }
                }
            });
    }

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

}