class RoutesAnswererUtil {

  public static List<DiffRoutesOutput> getRoutesDiff(
      Map<RouteRowKey, Map<RouteRowSecondaryKey, SortedSet<RouteRowAttribute>>> routesInBase,
      Map<RouteRowKey, Map<RouteRowSecondaryKey, SortedSet<RouteRowAttribute>>> routesInRef) {
    Set<RouteRowKey> allRouteKeys = new HashSet<>(routesInBase.keySet());
    allRouteKeys.addAll(routesInRef.keySet());

    List<DiffRoutesOutput> listDiffs = new ArrayList<>();
    for (RouteRowKey routeRowKey : allRouteKeys) {
      Map<RouteRowSecondaryKey, SortedSet<RouteRowAttribute>> baseAttrsForRowKey =
          routesInBase.get(routeRowKey);
      Map<RouteRowSecondaryKey, SortedSet<RouteRowAttribute>> refAttrsForRowKey =
          routesInRef.get(routeRowKey);

      if (baseAttrsForRowKey != null && refAttrsForRowKey != null) {
        // this network is present in routesInBase and routesInRef and respective values are
        // different
        if (!baseAttrsForRowKey.equals(refAttrsForRowKey)) {
          listDiffs.addAll(getDiffPerKey(routeRowKey, baseAttrsForRowKey, refAttrsForRowKey));
        }
      } else if (baseAttrsForRowKey != null) {
        baseAttrsForRowKey.forEach(
            (key, value) -> {
              // the nested list contains list of pairs of RouteRowAttributes with fist element and
              // second element of the pair from base and reference snapshots respectively, second
              // element is null to account for absence of this network in the reference snapshot
              List<List<RouteRowAttribute>> diffMatrix =
                  value.stream()
                      .map(routeRowAttribute -> Lists.newArrayList(routeRowAttribute, null))
                      .collect(Collectors.toList());
              listDiffs.add(
                  new DiffRoutesOutput(
                      routeRowKey,
                      key,
                      KeyPresenceStatus.ONLY_IN_SNAPSHOT,
                      diffMatrix,
                      KeyPresenceStatus.ONLY_IN_SNAPSHOT));
            });
      } else {
        refAttrsForRowKey.forEach(
            (key, value) -> {
              // the nested list contains list of pairs of RouteRowAttributes with fist element and
              // second element of the pair from base and reference snapshots respectively, first
              // element is null to account for absence of this network in the base snapshot
              List<List<RouteRowAttribute>> diffMatrix =
                  value.stream()
                      .map(routeRowAttribute -> Lists.newArrayList(null, routeRowAttribute))
                      .collect(Collectors.toList());
              listDiffs.add(
                  new DiffRoutesOutput(
                      routeRowKey,
                      key,
                      KeyPresenceStatus.ONLY_IN_REFERENCE,
                      diffMatrix,
                      KeyPresenceStatus.ONLY_IN_REFERENCE));
            });
      }
    }
    return listDiffs;
  }

}