// Path: consumer/app/src/main/java/au/com/dius/pactconsumer/data/exceptions/BadRequestException.java
// public class BadRequestException extends ServiceException {
// 
//   public BadRequestException() { }
// 
//   public BadRequestException(String message, Throwable cause) {
//     super(message, cause);
//   }
// 
// }
// 
// Path: consumer/app/src/main/java/au/com/dius/pactconsumer/data/model/ServiceResponse.java
// public class ServiceResponse {
// 
//   @Json(name = "valid_date")
//   private final DateTime validDate;
// 
//   @Json(name = "animals")
//   private final List<Animal> animals;
// 
//   public ServiceResponse(@Nullable DateTime validDate,
//                          @NonNull List<Animal> animals) {
//     this.validDate = validDate;
//     this.animals = animals;
//   }
// 
//   @Nullable
//   public DateTime getValidDate() {
//     return validDate;
//   }
// 
//   @NonNull
//   public List<Animal> getAnimals() {
//     return animals;
//   }
// 
//   @Override
//   public boolean equals(Object o) {
//     if (this == o) return true;
//     if (o == null || getClass() != o.getClass()) return false;
// 
//     ServiceResponse that = (ServiceResponse) o;
// 
//     long millis = validDate != null ? validDate.getMillis() : -1;
//     long thatMillis = that.validDate != null ? that.validDate.getMillis() : -1;
//     if (millis != thatMillis)
//       return false;
// 
//     return animals != null ? animals.equals(that.animals) : that.animals == null;
//   }
// 
//   @Override
//   public int hashCode() {
//     int result = validDate != null ? validDate.hashCode() : 0;
//     result = 31 * result + (animals != null ? animals.hashCode() : 0);
//     return result;
//   }
// 
//   @Override
//   public String toString() {
//     return "ServiceResponse{" +
//         "validDate=" + validDate +
//         ", animals=" + animals +
//         '}';
//   }
// 
//   public static ServiceResponse create(@NonNull DateTime validDate, @NonNull List<Animal> animals) {
//     return new ServiceResponse(validDate, animals);
//   }
// }
// 
// Path: consumer/app/src/main/java/au/com/dius/pactconsumer/util/DateHelper.java
// public final class DateHelper {
// 
//   private DateHelper() {
//   }
// 
//   public static String encodeDate(@Nullable DateTime dateTime) throws UnsupportedEncodingException {
//     if (dateTime == null) {
//       return null;
//     }
//     return URLEncoder.encode(toString(dateTime), "UTF-8");
//   }
// 
//   public static DateTime parse(@NonNull String value) {
//     return DateTime.parse(value);
//   }
// 
//   public static String toString(@NonNull DateTime value) {
//     return value.toString();
//   }
// 
// }


import android.support.annotation.NonNull;
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
import org.joda.time.DateTime;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import javax.inject.Inject;
import javax.inject.Singleton;
import au.com.dius.pactconsumer.data.exceptions.BadRequestException;
import au.com.dius.pactconsumer.data.model.ServiceResponse;
import au.com.dius.pactconsumer.util.DateHelper;
import io.reactivex.Single;
import retrofit2.http.GET;
import retrofit2.http.Query;
    Single<ServiceResponse> loadProviderJson(@Query("valid_date") String validDate);
  }

  private final Api api;

  @Inject
  public Service(@NonNull Api api) {
    this.api = api;
  }

  @NonNull
  @Override
  public Single<ServiceResponse> fetchResponse(@NonNull DateTime dateTime) {
    try {
      return api.loadProviderJson(DateHelper.encodeDate(dateTime))
          .onErrorResumeNext(this::mapError);
    } catch (UnsupportedEncodingException e) {
      return Single.error(e);
    }
  }

  private Single<ServiceResponse> mapError(Throwable throwable) {
    if (!(throwable instanceof HttpException)) {
      return Single.error(throwable);
    }

    HttpException exception = (HttpException) throwable;
    if (exception.code() == NOT_FOUND) {
      return Single.just(new ServiceResponse(null, Collections.emptyList()));
    } else if (exception.code() == BAD_REQUEST) {
// Path: consumer/app/src/main/java/au/com/dius/pactconsumer/data/exceptions/BadRequestException.java
// public class BadRequestException extends ServiceException {
// 
//   public BadRequestException() { }
// 
//   public BadRequestException(String message, Throwable cause) {
//     super(message, cause);
//   }
// 
// }
// 
// Path: consumer/app/src/main/java/au/com/dius/pactconsumer/data/model/ServiceResponse.java
// public class ServiceResponse {
// 
//   @Json(name = "valid_date")
//   private final DateTime validDate;
// 
//   @Json(name = "animals")
//   private final List<Animal> animals;
// 
//   public ServiceResponse(@Nullable DateTime validDate,
//                          @NonNull List<Animal> animals) {
//     this.validDate = validDate;
//     this.animals = animals;
//   }
// 
//   @Nullable
//   public DateTime getValidDate() {
//     return validDate;
//   }
// 
//   @NonNull
//   public List<Animal> getAnimals() {
//     return animals;
//   }
// 
//   @Override
//   public boolean equals(Object o) {
//     if (this == o) return true;
//     if (o == null || getClass() != o.getClass()) return false;
// 
//     ServiceResponse that = (ServiceResponse) o;
// 
//     long millis = validDate != null ? validDate.getMillis() : -1;
//     long thatMillis = that.validDate != null ? that.validDate.getMillis() : -1;
//     if (millis != thatMillis)
//       return false;
// 
//     return animals != null ? animals.equals(that.animals) : that.animals == null;
//   }
// 
//   @Override
//   public int hashCode() {
//     int result = validDate != null ? validDate.hashCode() : 0;
//     result = 31 * result + (animals != null ? animals.hashCode() : 0);
//     return result;
//   }
// 
//   @Override
//   public String toString() {
//     return "ServiceResponse{" +
//         "validDate=" + validDate +
//         ", animals=" + animals +
//         '}';
//   }
// 
//   public static ServiceResponse create(@NonNull DateTime validDate, @NonNull List<Animal> animals) {
//     return new ServiceResponse(validDate, animals);
//   }
// }
// 
// Path: consumer/app/src/main/java/au/com/dius/pactconsumer/util/DateHelper.java
// public final class DateHelper {
// 
//   private DateHelper() {
//   }
// 
//   public static String encodeDate(@Nullable DateTime dateTime) throws UnsupportedEncodingException {
//     if (dateTime == null) {
//       return null;
//     }
//     return URLEncoder.encode(toString(dateTime), "UTF-8");
//   }
// 
//   public static DateTime parse(@NonNull String value) {
//     return DateTime.parse(value);
//   }
// 
//   public static String toString(@NonNull DateTime value) {
//     return value.toString();
//   }
// 
// }


// Path: consumer/app/src/main/java/au/com/dius/pactconsumer/data/Service.java
import android.support.annotation.NonNull;
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
import org.joda.time.DateTime;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import javax.inject.Inject;
import javax.inject.Singleton;
import au.com.dius.pactconsumer.data.exceptions.BadRequestException;
import au.com.dius.pactconsumer.data.model.ServiceResponse;
import au.com.dius.pactconsumer.util.DateHelper;
import io.reactivex.Single;
import retrofit2.http.GET;
import retrofit2.http.Query;

    Single<ServiceResponse> loadProviderJson(@Query("valid_date") String validDate);
  }

  private final Api api;

  @Inject
  public Service(@NonNull Api api) {
    this.api = api;
  }

  @NonNull
  @Override
  public Single<ServiceResponse> fetchResponse(@NonNull DateTime dateTime) {
    try {
      return api.loadProviderJson(DateHelper.encodeDate(dateTime))
          .onErrorResumeNext(this::mapError);
    } catch (UnsupportedEncodingException e) {
      return Single.error(e);
    }
  }

  private Single<ServiceResponse> mapError(Throwable throwable) {
    if (!(throwable instanceof HttpException)) {
      return Single.error(throwable);
    }

    HttpException exception = (HttpException) throwable;
    if (exception.code() == NOT_FOUND) {
      return Single.just(new ServiceResponse(null, Collections.emptyList()));
    } else if (exception.code() == BAD_REQUEST) {
      return Single.error(new BadRequestException(exception.message(), exception));