/*
* Copyright (C) 2013 Alex Kuiper
*
* This file is part of PageTurner
*
* PageTurner is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PageTurner is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PageTurner. If not, see <http://www.gnu.org/licenses/>.*
*/
package net.nightwhistler.pageturner.fragment;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.github.rtyley.android.sherlock.roboguice.fragment.RoboSherlockFragment;
import com.google.inject.Inject;
import com.google.inject.Provider;
import jedi.option.Option;
import net.nightwhistler.nucular.atom.Entry;
import net.nightwhistler.nucular.atom.Feed;
import net.nightwhistler.nucular.atom.Link;
import net.nightwhistler.pageturner.Configuration;
import net.nightwhistler.pageturner.R;
import net.nightwhistler.pageturner.activity.ReadingActivity;
import net.nightwhistler.pageturner.catalog.Catalog;
import net.nightwhistler.pageturner.catalog.DownloadFileTask;
import net.nightwhistler.pageturner.catalog.LoadFeedCallback;
import net.nightwhistler.pageturner.catalog.LoadThumbnailTask;
import roboguice.inject.InjectView;
import javax.annotation.Nullable;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Random;
import static jedi.functional.FunctionalPrimitives.isEmpty;
/**
* Fragment which shows the details of the book to be downloaded.
*/
public class BookDetailsFragment extends RoboSherlockFragment implements LoadFeedCallback {
@Inject
private Provider<LoadThumbnailTask> loadThumbnailTaskProvider;
@Inject
private Provider<DownloadFileTask> downloadFileTaskProvider;
@Inject
private Provider<DisplayMetrics> metricsProvider;
@InjectView(R.id.mainLayout)
private View mainLayout;
@InjectView(R.id.itemAuthor)
private TextView authorTextView;
@InjectView(R.id.itemIcon)
private ImageView icon;
@InjectView(R.id.buyNowButton)
private Button buyNowButton;
@InjectView(R.id.firstDivider)
@Nullable
private View divider;
@InjectView(R.id.readNowButton)
private Button downloadButton;
@InjectView(R.id.addToLibraryButton)
private Button addToLibraryButton;
@Inject
private Configuration config;
@Inject
private NotificationManager notificationManager;
private Feed feed;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.catalog_download, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
DisplayMetrics metrics = metricsProvider.get();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if ( this.feed != null ) {
doSetFeed(feed);
}
}
private void doSetFeed(Feed feed) {
//If we're here, the feed always has just 1 entry
final Entry entry = feed.getEntries().get(0);
Option<Link> epubLink = entry.getEpubLink();
if ( ! isEmpty(epubLink) ) {
String base = feed.getURL();
try {
final URL url = new URL(new URL(base), epubLink.unsafeGet().getHref());
downloadButton.setOnClickListener( v -> startDownload(true, url.toExternalForm() ));
addToLibraryButton.setOnClickListener( v -> startDownload(false, url.toExternalForm()));
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
} else {
downloadButton.setVisibility(View.GONE);
addToLibraryButton.setVisibility(View.GONE);
}
Option<Link> buyLink = entry.getBuyLink();
if ( !isEmpty( buyLink ) ) {
buyNowButton.setOnClickListener( v -> {
String url = buyLink.unsafeGet().getHref();
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
});
} else {
buyNowButton.setVisibility(View.GONE);
if ( divider != null ) {
divider.setVisibility(View.GONE);
}
}
if (entry.getAuthor() != null) {
String authorText = String.format(
getString(R.string.book_by), entry.getAuthor()
.getName());
authorTextView.setText(authorText);
} else {
authorTextView.setText("");
}
final Option<Link> imgLink = Catalog.getImageLink(feed, entry);
Catalog.loadBookDetails(mainLayout, entry, false);
icon.setImageDrawable( getActivity().getResources().getDrawable(R.drawable.unknown_cover));
LoadThumbnailTask task = this.loadThumbnailTaskProvider.get();
task.setLoadFeedCallback(this);
task.setBaseUrl(feed.getURL());
imgLink.forEach( task::execute );
}
@Override
public void setNewFeed(Feed feed, ResultType resultType) {
this.feed = feed;
if ( this.downloadButton != null ) {
doSetFeed(feed);
}
}
@Override
public void errorLoadingFeed(String error) {
Toast.makeText(getActivity(), error, Toast.LENGTH_LONG ).show();
}
@Override
public void emptyFeedLoaded(Feed feed) {
errorLoadingFeed( getActivity().getString(R.string.empty_opds_feed) );
}
private void setSupportProgressBarIndeterminateVisibility(boolean enable) {
SherlockFragmentActivity activity = getSherlockActivity();
if ( activity != null) {
activity.setSupportProgressBarIndeterminateVisibility(enable);
}
}
public void notifyLinkUpdated( Link link, Drawable drawable ) {
if ( drawable != null ) {
icon.setImageDrawable(drawable);
}
onLoadingDone();
}
@Override
public void onLoadingStart() {
setSupportProgressBarIndeterminateVisibility(true);
}
private void onLoadingDone() {
setSupportProgressBarIndeterminateVisibility(false);
}
public void startDownload(final boolean openOnCompletion, final String url) {
if ( feed == null || feed.getEntries() == null || feed.getEntries().size() == 0 ) {
return;
}
final DownloadFileTask task = this.downloadFileTaskProvider.get();
final Entry entry = feed.getEntries().get(0);
String title = entry.getTitle();
if ( !openOnCompletion && Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH ) {
task.setCallBack( new NotificationBarCallback(getActivity().getBaseContext(), title, openOnCompletion) );
} else {
task.setCallBack( new ProgressDialogCallback(getActivity().getBaseContext(), task, openOnCompletion) );
}
task.execute(url);
}
private abstract class AbstractDownloadCallback implements DownloadFileTask.DownloadFileCallback {
private boolean openOnCompletion;
private Context context;
public AbstractDownloadCallback( Context context, boolean openOnCompletion ) {
this.openOnCompletion = openOnCompletion;
this.context = context;
}
@Override
public void downloadSuccess(File destFile) {
if ( ! isAdded() ) {
return;
}
if ( openOnCompletion ) {
Intent intent = getBookOpenIntent(destFile);
startActivity(intent);
getActivity().finish();
}
}
protected Intent getBookOpenIntent(File destFile) {
Intent intent;
intent = new Intent(context,
ReadingActivity.class);
config.setLastActivity( ReadingActivity.class );
intent.setData(Uri.parse(destFile.getAbsolutePath()));
return intent;
}
public boolean isOpenOnCompletion() {
return openOnCompletion;
}
}
private class NotificationBarCallback extends AbstractDownloadCallback {
private NotificationCompat.Builder builder;
final private String title;
final private String downloadSubtitle;
final private String downloadSuccess;
final private String downloadFailed;
int notificationId;
private Context context;
public NotificationBarCallback(Context context, String title,
boolean openOnCompletion) {
super( context, openOnCompletion );
this.title = title;
this.downloadSubtitle = getString(R.string.downloading);
this.downloadSuccess = getString(R.string.download_complete);
this.downloadFailed = getString(R.string.book_failed);
this.notificationId = new Random().nextInt();
this.context = context;
}
@Override
public void onDownloadStart() {
builder = new NotificationCompat.Builder(context);
builder.setContentTitle(title)
.setContentText(downloadSubtitle)
.setSmallIcon(R.drawable.download);
builder.setTicker(downloadSubtitle);
builder.setProgress( 0, 0, true);
notificationManager.notify(notificationId, builder.build());
}
@Override
public void progressUpdate(long progress, long total, int percentage) {
builder.setProgress( 100, percentage, false);
// Displays the progress bar for the first time.
notificationManager.notify(notificationId, builder.build());
}
@Override
public void downloadSuccess(File destFile) {
builder.setContentText(downloadSuccess)
// Removes the progress bar
.setProgress(0, 0, false);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
getBookOpenIntent(destFile), 0);
builder.setContentIntent( contentIntent );
builder.setTicker(downloadSuccess);
builder.setAutoCancel(true);
notificationManager.notify(notificationId, builder.build());
super.downloadSuccess(destFile);
}
@Override
public void downloadFailed() {
builder.setContentText(downloadFailed)
// Removes the progress bar
.setProgress(0, 0, false);
builder.setAutoCancel(true);
notificationManager.notify(notificationId, builder.build());
}
}
private class ProgressDialogCallback extends AbstractDownloadCallback implements
DialogInterface.OnCancelListener {
private ProgressDialog downloadDialog;
private DownloadFileTask task;
private ProgressDialogCallback(Context context, DownloadFileTask task, boolean openOnCompletion) {
super( context, openOnCompletion );
this.downloadDialog = new ProgressDialog(getActivity());
this.task = task;
downloadDialog.setIndeterminate(false);
downloadDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
downloadDialog.setCancelable(true);
downloadDialog.setOnCancelListener( this );
}
@Override
public void onCancel(DialogInterface dialog) {
task.cancel(true);
}
@Override
public void onDownloadStart() {
downloadDialog.setMessage(getString(R.string.downloading));
downloadDialog.show();
}
@Override
public void progressUpdate(long progress, long total, int percentage) {
downloadDialog.setMax( Long.valueOf(total).intValue() );
downloadDialog.setProgress(Long.valueOf(progress).intValue());
}
@Override
public void downloadSuccess(File destFile) {
downloadDialog.dismiss();
super.downloadSuccess(destFile);
if ( ! isOpenOnCompletion() ) {
Toast.makeText(getActivity(), R.string.download_complete,
Toast.LENGTH_LONG).show();
}
}
@Override
public void downloadFailed() {
downloadDialog.dismiss();
if ( isAdded() ) {
Toast.makeText(getActivity(), R.string.book_failed,
Toast.LENGTH_LONG).show();
}
}
}
}