/**
   * If just one of the five heroes in the list is different from last time then we don't want to
   * make the server get advantages data on all of them. This method returns an observable that just
   * queries the server for advantages data on the new hero (the one at differencePos) and then
   * updates the earlier advantages info with that new hero.
   *
   * @param oldAdvantagesData
   * @param heroesInPhoto
   * @param differencePos
   * @param advantagesApi
   * @return
   */
  private static Observable<List<HeroAndAdvantages>> getSingleHeroChangedObservable(
      final List<HeroAndAdvantages> oldAdvantagesData,
      List<String> heroesInPhoto,
      final int differencePos,
      AdvantagesApi advantagesApi) {
    final List<HeroAndAdvantages> advantagesData = SqlLoader.deepCopyOfHeroes(oldAdvantagesData);

    // The single hero that has changed is blank, we can just set all the advantages to
    // neutral and return that.
    if (heroesInPhoto.get(differencePos).equals("")) {
      for (HeroAndAdvantages hero : advantagesData) {
        hero.setAdvantage(HeroAndAdvantages.NEUTRAL_ADVANTAGE, differencePos);
      }
      return Observable.just(advantagesData);
    }

    heroesInPhoto = prepareNamesForWebQuery(heroesInPhoto);

    return advantagesApi
        .getSingeAdvantage(heroesInPhoto.get(differencePos))
        .map(
            new Func1<AdvantageData, List<HeroAndAdvantages>>() {
              @Override
              public List<HeroAndAdvantages> call(AdvantageData newAdvantageData) {
                return AdvantageData.mergeIntoAdvantagesList(
                    advantagesData, newAdvantageData, differencePos);
              }
            })
        .timeout(SINGlE_QUERY_TIMEOUT, TimeUnit.MILLISECONDS);
  }
  /**
   * If we only have one hero in the list of heroes then we don't need to ask the server to get full
   * advantages data, we can just ask it to get advantages data for the one hero. This returns an
   * observable which does that.
   *
   * @param advantagesApi
   * @param singleHeroPos
   * @param heroesInPhoto
   * @return
   */
  private static Observable<List<HeroAndAdvantages>> getSingleNewHeroObservable(
      AdvantagesApi advantagesApi, final int singleHeroPos, List<String> heroesInPhoto) {

    return advantagesApi
        .getSingeAdvantage(heroesInPhoto.get(singleHeroPos))
        .map(
            new Func1<AdvantageData, List<HeroAndAdvantages>>() {
              @Override
              public List<HeroAndAdvantages> call(AdvantageData newAdvantageData) {
                return AdvantageData.createAdvantagesListFromSingleAdvantage(
                    newAdvantageData, singleHeroPos);
              }
            })
        .timeout(SINGlE_QUERY_TIMEOUT, TimeUnit.MILLISECONDS);
  }
  /**
   * Returns an observable which queries the server to find advantages data on the five heroes
   * listed in heroesInPhoto.
   *
   * @param advantagesApi
   * @param heroesInPhoto
   * @return
   */
  private static Observable<List<HeroAndAdvantages>> getFullObservable(
      AdvantagesApi advantagesApi, List<String> heroesInPhoto) {
    heroesInPhoto = prepareNamesForWebQuery(heroesInPhoto);

    return advantagesApi
        .getAdvantages(
            heroesInPhoto.get(0),
            heroesInPhoto.get(1),
            heroesInPhoto.get(2),
            heroesInPhoto.get(3),
            heroesInPhoto.get(4))
        .map(
            new Func1<AdvantageData, List<HeroAndAdvantages>>() {
              @Override
              public List<HeroAndAdvantages> call(AdvantageData advantageData) {
                return AdvantageData.createFullAdvantagesList(advantageData);
              }
            })
        .timeout(FULL_QUERY_TIMEOUT, TimeUnit.MILLISECONDS);
  }