package org.bookdash.android.data.book; import android.net.Uri; import android.support.annotation.WorkerThread; import android.util.Log; import com.google.firebase.storage.FileDownloadTask; import com.google.firebase.storage.FirebaseStorage; import com.google.gson.Gson; import org.bookdash.android.BookDashApplication; import org.bookdash.android.data.utils.FileManager; import org.bookdash.android.data.utils.ZipManager; import org.bookdash.android.domain.model.DownloadProgressItem; import org.bookdash.android.domain.model.firebase.FireBookDetails; import org.bookdash.android.domain.model.gson.BookPages; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import rx.Observable; import rx.functions.Func0; import rx.functions.Func1; public class DownloadServiceImpl implements DownloadService { public static final String TAG = "DownloadService"; private final FirebaseStorage storageRef; public DownloadServiceImpl(FirebaseStorage firebaseStorageRef) { this.storageRef = firebaseStorageRef; } @Override public Observable<DownloadProgressItem> downloadFile(final FireBookDetails book) { if (book.isDownloadedAlready()) { return getBookPagesFromDownloadedBook(book); } try { final File localFile; Uri uri = Uri.parse(book.getBookUrl()); String tempFileName = uri.getLastPathSegment(); String tempFileParsed[] = tempFileName.split("/"); tempFileName = tempFileParsed[tempFileParsed.length - 1]; localFile = File.createTempFile(tempFileName, ""); return RxFirebaseStorage.getFile(book.getBookUrlStorageRef(), localFile) .flatMap(new Func1<FileDownloadTask.TaskSnapshot, Observable<DownloadProgressItem>>() { @Override public Observable<DownloadProgressItem> call(FileDownloadTask.TaskSnapshot taskSnapshot) { DownloadProgressItem downloadProgressItem = new DownloadProgressItem( taskSnapshot.getBytesTransferred(), taskSnapshot.getTotalByteCount()); if (downloadProgressItem.isComplete()) { return Observable .defer(new TransformFileIntoBookPages(downloadProgressItem, localFile, book)); } return Observable.just(downloadProgressItem); } }); } catch (Exception e) { Log.e(TAG, "IOException downloading file", e); return Observable.error(e); } } private Observable<DownloadProgressItem> getBookPagesFromDownloadedBook(final FireBookDetails bookDetails) { return Observable.defer(new Func0<Observable<DownloadProgressItem>>() { @Override public Observable<DownloadProgressItem> call() { BookPages bookPages = getBookPages( bookDetails.getFolderLocation() + File.separator + FireBookDetails.BOOK_FORMAT_JSON_FILE); DownloadProgressItem downloadProgressItem = new DownloadProgressItem(100, 100); downloadProgressItem.setBookPages(bookPages); return Observable.just(downloadProgressItem); } }); } private BookPages getBookPages(String fileName) { Gson gson = new Gson(); BufferedReader br = null; BookPages bookPages = null; try { br = new BufferedReader(new FileReader(fileName)); bookPages = gson.fromJson(br, BookPages.class); } catch (FileNotFoundException e) { try { if (br != null) { br.close(); } } catch (IOException e1) { Log.e(TAG, "EX: ", e); } Log.e(TAG, "Ex:" + e.getMessage(), e); } catch (Exception e) { Log.e(TAG, "error parsing book: " + fileName, e); } return bookPages; } public Observable<Boolean> deleteDownload(final FireBookDetails bookToDelete) { return Observable.defer(new Func0<Observable<Boolean>>() { @Override public Observable<Boolean> call() { return Observable.just(deleteLocalBook(bookToDelete)); } }); } @WorkerThread private boolean deleteLocalBook(FireBookDetails book) { FileManager.deleteFolder(book.getFolderLocation()); FileManager.deleteFolder(BookDashApplication.FILES_DIR + File.separator + book.getId()); return true; } private class TransformFileIntoBookPages implements Func0<Observable<DownloadProgressItem>> { private final File file; private final FireBookDetails book; DownloadProgressItem downloadProgressItem; TransformFileIntoBookPages(DownloadProgressItem downloadProgressItem, File localFile, FireBookDetails book) { this.downloadProgressItem = downloadProgressItem; this.book = book; this.file = localFile; } @Override public Observable<DownloadProgressItem> call() { String targetLocation = BookDashApplication.FILES_DIR + File.separator + book.getId(); ZipManager zipManager = new ZipManager(); zipManager.unzip(file.getAbsolutePath(), targetLocation); BookPages bookPages = getBookPages( book.getFolderLocation() + File.separator + FireBookDetails.BOOK_FORMAT_JSON_FILE); downloadProgressItem.setBookPages(bookPages); return Observable.just(downloadProgressItem); } } }