private void checkDownloadIsSuccessful(final Download download) {
   int actualProgress = 0;
   int status = Download.DOWNLOADED;
   // If any page has an error, the download result will be error
   for (Page page : download.pages) {
     actualProgress += page.getProgress();
     if (page.getStatus() != Page.READY) status = Download.ERROR;
   }
   // Ensure that the chapter folder has all the images
   if (!isChapterDownloaded(download.directory, download.pages)) {
     status = Download.ERROR;
   }
   download.totalProgress = actualProgress;
   download.setStatus(status);
   // Delete successful downloads from queue after notifying
   if (status == Download.DOWNLOADED) {
     queue.remove(download);
   }
 }
  // Get the image from the filesystem if it exists or download from network
  private Observable<Page> getOrDownloadImage(final Page page, Download download) {
    // If the image URL is empty, do nothing
    if (page.getImageUrl() == null) return Observable.just(page);

    String filename = getImageFilename(page);
    File imagePath = new File(download.directory, filename);

    // If the image is already downloaded, do nothing. Otherwise download from network
    Observable<Page> pageObservable =
        isImageDownloaded(imagePath)
            ? Observable.just(page)
            : downloadImage(page, download.source, download.directory, filename);

    return pageObservable
        // When the image is ready, set image path, progress (just in case) and status
        .doOnNext(
            p -> {
              page.setImagePath(imagePath.getAbsolutePath());
              page.setProgress(100);
              download.downloadedImages++;
              page.setStatus(Page.READY);
            })
        // Mark this page as error and allow to download the remaining
        .onErrorResumeNext(
            e -> {
              page.setProgress(0);
              page.setStatus(Page.ERROR);
              return Observable.just(page);
            });
  }
 // Save image on disk
 private Observable<Page> downloadImage(
     Page page, Source source, File directory, String filename) {
   page.setStatus(Page.DOWNLOAD_IMAGE);
   return source
       .getImageProgressResponse(page)
       .flatMap(
           resp -> {
             try {
               DiskUtils.saveBufferedSourceToDirectory(resp.body().source(), directory, filename);
             } catch (Exception e) {
               Timber.e(e.getCause(), e.getMessage());
               return Observable.error(e);
             }
             return Observable.just(page);
           })
       .retry(2);
 }
  // Public method to get the image from the filesystem. It does NOT provide any way to download the
  // image
  public Observable<Page> getDownloadedImage(final Page page, File chapterDir) {
    if (page.getImageUrl() == null) {
      page.setStatus(Page.ERROR);
      return Observable.just(page);
    }

    File imagePath = new File(chapterDir, getImageFilename(page));

    // When the image is ready, set image path, progress (just in case) and status
    if (isImageDownloaded(imagePath)) {
      page.setImagePath(imagePath.getAbsolutePath());
      page.setProgress(100);
      page.setStatus(Page.READY);
    } else {
      page.setStatus(Page.ERROR);
    }
    return Observable.just(page);
  }
 // Get the filename for an image given the page
 private String getImageFilename(Page page) {
   String url = page.getImageUrl();
   return url.substring(url.lastIndexOf("/") + 1, url.length());
 }