/*
* Copyright (C) 2010-2011 Geometer Plus <contact@geometerplus.com>
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.android.fbreader.network;
import java.util.Set;
import java.util.LinkedHashSet;
import java.io.File;
import android.app.AlertDialog;
import android.app.Activity;
import android.os.Message;
import android.os.Handler;
import android.net.Uri;
import android.content.Intent;
import android.content.DialogInterface;
import android.view.Menu;
import android.view.ContextMenu;
import org.geometerplus.zlibrary.core.resources.ZLResource;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.zlibrary.ui.androidfly.R;
import org.geometerplus.android.util.UIUtil;
import org.geometerplus.android.fbreader.FBReader;
import org.geometerplus.fbreader.network.*;
import org.geometerplus.fbreader.network.tree.NetworkBookTree;
import org.geometerplus.fbreader.network.tree.NetworkAuthorTree;
import org.geometerplus.fbreader.network.tree.NetworkSeriesTree;
import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationManager;
class NetworkBookActions extends NetworkTreeActions {
public static final int DOWNLOAD_BOOK_ITEM_ID = 0;
public static final int DOWNLOAD_DEMO_ITEM_ID = 1;
public static final int READ_BOOK_ITEM_ID = 2;
public static final int READ_DEMO_ITEM_ID = 3;
public static final int DELETE_BOOK_ITEM_ID = 4;
public static final int DELETE_DEMO_ITEM_ID = 5;
public static final int BUY_DIRECTLY_ITEM_ID = 6;
public static final int BUY_IN_BROWSER_ITEM_ID = 7;
public static final int SHOW_BOOK_ACTIVITY_ITEM_ID = 8;
public static final int SHOW_BOOKS_ITEM_ID = 9;
public static final int ADD_BOOK_TO_BASKET = 10;
public static final int REMOVE_BOOK_FROM_BASKET = 11;
public static final int ADD_CATALOG_TO_FAVORITES = 12;
public static final int REMOVE_CATALOG_FROM_FAVORITES = 13;
private static boolean useFullReferences(NetworkBookItem book) {
return book.reference(BookReference.Type.DOWNLOAD_FULL) != null ||
book.reference(BookReference.Type.DOWNLOAD_FULL_CONDITIONAL) != null;
}
private static boolean useDemoReferences(NetworkBookItem book) {
return book.reference(BookReference.Type.DOWNLOAD_DEMO) != null &&
book.localCopyFileName() == null &&
book.reference(BookReference.Type.DOWNLOAD_FULL) == null;
}
private static boolean useBuyReferences(NetworkBookItem book) {
return book.localCopyFileName() == null &&
book.reference(BookReference.Type.DOWNLOAD_FULL) == null;
}
@Override
public boolean canHandleTree(NetworkTree tree) {
return tree instanceof NetworkBookTree
|| tree instanceof NetworkAuthorTree
|| tree instanceof NetworkSeriesTree;
}
@Override
public void buildContextMenu(Activity activity, ContextMenu menu, NetworkTree tree) {
menu.setHeaderTitle(tree.getName());
if (tree instanceof NetworkAuthorTree || tree instanceof NetworkSeriesTree) {
addMenuItem(menu, SHOW_BOOKS_ITEM_ID, "showBooks");
return;
}
final NetworkBookTree bookTree = (NetworkBookTree) tree;
final NetworkBookItem book = bookTree.Book;
Set<Action> actions = getContextMenuActions(book, ((NetworkBaseActivity)activity).Connection);
for (Action a: actions) {
if (a.Arg == null) {
addMenuItem(menu, a.Id, a.Key);
} else {
addMenuItem(menu, a.Id, a.Key, a.Arg);
}
}
}
static class Action {
public final int Id;
public final String Key;
public final String Arg;
public Action(int id, String key) {
Id = id;
Key = key;
Arg = null;
}
public Action(int id, String key, String arg) {
Id = id;
Key = key;
Arg = arg;
}
}
static int getBookStatus(NetworkBookItem book, BookDownloaderServiceConnection connection) {
if (useFullReferences(book)) {
BookReference reference = book.reference(BookReference.Type.DOWNLOAD_FULL);
if (reference != null
&& connection != null && connection.isBeingDownloaded(reference.URL)) {
return R.drawable.ic_list_download;
} else if (book.localCopyFileName() != null) {
return R.drawable.ic_list_flag;
} else if (reference != null) {
return R.drawable.ic_list_download;
}
}
if (useBuyReferences(book)
&& book.reference(BookReference.Type.BUY) != null
|| book.reference(BookReference.Type.BUY_IN_BROWSER) != null) {
return R.drawable.ic_list_buy;
}
return 0;
}
static Set<Action> getContextMenuActions(NetworkBookItem book, BookDownloaderServiceConnection connection) {
LinkedHashSet<Action> actions = new LinkedHashSet<Action>();
if (useFullReferences(book)) {
BookReference reference = book.reference(BookReference.Type.DOWNLOAD_FULL);
if (reference != null
&& connection != null && connection.isBeingDownloaded(reference.URL)) {
actions.add(new Action(TREE_NO_ACTION, "alreadyDownloading"));
} else if (book.localCopyFileName() != null) {
actions.add(new Action(READ_BOOK_ITEM_ID, "read"));
actions.add(new Action(DELETE_BOOK_ITEM_ID, "delete"));
} else if (reference != null) {
actions.add(new Action(DOWNLOAD_BOOK_ITEM_ID, "download"));
}
}
if (useDemoReferences(book)) {
BookReference reference = book.reference(BookReference.Type.DOWNLOAD_DEMO);
if (connection != null && connection.isBeingDownloaded(reference.URL)) {
actions.add(new Action(TREE_NO_ACTION, "alreadyDownloadingDemo"));
} else if (reference.localCopyFileName(BookReference.Type.DOWNLOAD_DEMO) != null) {
actions.add(new Action(READ_DEMO_ITEM_ID, "readDemo"));
actions.add(new Action(DELETE_DEMO_ITEM_ID, "deleteDemo"));
} else {
actions.add(new Action(DOWNLOAD_DEMO_ITEM_ID, "downloadDemo"));
}
}
if (useBuyReferences(book)) {
int id = TREE_NO_ACTION;
BookReference reference = null;
if (book.reference(BookReference.Type.BUY) != null) {
reference = book.reference(BookReference.Type.BUY);
id = BUY_DIRECTLY_ITEM_ID;
} else if (book.reference(BookReference.Type.BUY_IN_BROWSER) != null) {
reference = book.reference(BookReference.Type.BUY_IN_BROWSER);
id = BUY_IN_BROWSER_ITEM_ID;
}
if (reference != null) {
final String price = ((BuyBookReference) reference).Price;
actions.add(new Action(id, "buy", price));
}
final Basket basket = book.Link.basket();
if (basket != null) {
if (basket.contains(book)) {
actions.add(new Action(REMOVE_BOOK_FROM_BASKET, "removeFromBasket"));
} else {
actions.add(new Action(ADD_BOOK_TO_BASKET, "addToBasket"));
}
}
}
return actions;
}
@Override
public int getDefaultActionCode(NetworkBaseActivity activity, NetworkTree tree) {
if (tree instanceof NetworkAuthorTree || tree instanceof NetworkSeriesTree) {
return SHOW_BOOKS_ITEM_ID;
}
return SHOW_BOOK_ACTIVITY_ITEM_ID;
}
@Override
public String getConfirmText(NetworkTree tree, int actionCode) {
return null;
}
@Override
public boolean createOptionsMenu(Menu menu, NetworkTree tree) {
return false;
}
@Override
public boolean prepareOptionsMenu(NetworkBaseActivity activity, Menu menu, NetworkTree tree) {
return false;
}
@Override
public boolean runAction(NetworkBaseActivity activity, NetworkTree tree, int actionCode) {
if (tree instanceof NetworkAuthorTree || tree instanceof NetworkSeriesTree) {
switch (actionCode) {
case SHOW_BOOKS_ITEM_ID:
Util.openTree(activity, tree);
return true;
}
return false;
} else if (tree instanceof NetworkBookTree) {
return runActionStatic(activity, ((NetworkBookTree)tree), actionCode);
} else {
return false;
}
}
static boolean runActionStatic(Activity activity, NetworkBookTree tree, int actionCode) {
switch (actionCode) {
case SHOW_BOOK_ACTIVITY_ITEM_ID:
Util.openTree(activity, tree);
return true;
default:
return runActionStatic(activity, tree.Book, actionCode);
}
}
static boolean runActionStatic(Activity activity, NetworkBookItem book, int actionCode) {
switch (actionCode) {
case DOWNLOAD_BOOK_ITEM_ID:
doDownloadBook(activity, book, false);
return true;
case DOWNLOAD_DEMO_ITEM_ID:
doDownloadBook(activity, book, true);
return true;
case READ_BOOK_ITEM_ID:
doReadBook(activity, book, false);
return true;
case READ_DEMO_ITEM_ID:
doReadBook(activity, book, true);
return true;
case DELETE_BOOK_ITEM_ID:
tryToDeleteBook(activity, book, false);
return true;
case DELETE_DEMO_ITEM_ID:
tryToDeleteBook(activity, book, true);
return true;
case BUY_DIRECTLY_ITEM_ID:
doBuyDirectly(activity, book);
return true;
case BUY_IN_BROWSER_ITEM_ID:
doBuyInBrowser(activity, book);
return true;
case ADD_BOOK_TO_BASKET:
book.Link.basket().add(book);
return true;
case REMOVE_BOOK_FROM_BASKET:
book.Link.basket().remove(book);
return true;
}
return false;
}
private static void doDownloadBook(Activity activity, final NetworkBookItem book, boolean demo) {
int resolvedType = demo ? BookReference.Type.DOWNLOAD_DEMO : BookReference.Type.DOWNLOAD_FULL;
BookReference ref = book.reference(resolvedType);
if (ref != null) {
final String sslCertificate;
if (book.Link.authenticationManager() != null) {
sslCertificate = book.Link.authenticationManager().SSLCertificate;
} else {
sslCertificate = null;
}
activity.startService(
new Intent(Intent.ACTION_VIEW, Uri.parse(ref.URL),
activity.getApplicationContext(), BookDownloaderService.class)
.putExtra(BookDownloaderService.BOOK_FORMAT_KEY, ref.BookFormat)
.putExtra(BookDownloaderService.REFERENCE_TYPE_KEY, resolvedType)
.putExtra(BookDownloaderService.CLEAN_URL_KEY, ref.cleanURL())
.putExtra(BookDownloaderService.TITLE_KEY, book.Title)
.putExtra(BookDownloaderService.SSL_CERTIFICATE_KEY, sslCertificate)
);
}
}
private static void doReadBook(Activity activity, final NetworkBookItem book, boolean demo) {
String local = null;
if (!demo) {
local = book.localCopyFileName();
} else {
BookReference reference = book.reference(BookReference.Type.DOWNLOAD_DEMO);
if (reference != null) {
local = reference.localCopyFileName(BookReference.Type.DOWNLOAD_DEMO);
}
}
if (local != null) {
activity.startActivity(
new Intent(Intent.ACTION_VIEW,
Uri.fromFile(new File(local)),
activity.getApplicationContext(),
FBReader.class
).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK)
);
}
}
private static void tryToDeleteBook(Activity activity, final NetworkBookItem book, final boolean demo) {
final ZLResource dialogResource = ZLResource.resource("dialog");
final ZLResource buttonResource = dialogResource.getResource("button");
final ZLResource boxResource = dialogResource.getResource("deleteBookBox");
new AlertDialog.Builder(activity)
.setTitle(book.Title)
.setMessage(boxResource.getResource("message").getValue())
.setIcon(0)
.setPositiveButton(buttonResource.getResource("yes").getValue(), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO: remove information about book from Library???
if (!demo) {
book.removeLocalFiles();
} else {
final BookReference reference = book.reference(BookReference.Type.DOWNLOAD_DEMO);
if (reference != null) {
final String fileName = reference.localCopyFileName(BookReference.Type.DOWNLOAD_DEMO);
if (fileName != null) {
new File(fileName).delete();
}
}
}
if (NetworkView.Instance().isInitialized()) {
NetworkView.Instance().fireModelChangedAsync();
}
}
})
.setNegativeButton(buttonResource.getResource("no").getValue(), null)
.create().show();
}
private static void doBuyDirectly(final Activity activity, final NetworkBookItem book) {
final NetworkAuthenticationManager mgr = book.Link.authenticationManager();
if (mgr == null) {
return;
}
/*if (!NetworkOperationRunnable::tryConnect()) {
return;
}*/
final ZLResource dialogResource = ZLResource.resource("dialog");
final ZLResource buttonResource = dialogResource.getResource("button");
final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_NEGATIVE) {
return;
}
if (!mgr.needPurchase(book)) {
return;
}
final boolean downloadBook = which == DialogInterface.BUTTON_NEUTRAL;
final Handler handler = new Handler() {
public void handleMessage(Message message) {
final ZLNetworkException exception = (ZLNetworkException)message.obj;
if (exception != null) {
String buttonKey;
DialogInterface.OnClickListener action = null;
if (NetworkException.ERROR_PURCHASE_NOT_ENOUGH_MONEY.equals(
exception.getCode())
) {
buttonKey = "refillAccount";
action = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
new RefillAccountActions().runStandalone(activity, book.Link);
}
};
} else {
buttonKey = "ok";
}
final ZLResource boxResource = dialogResource.getResource("networkError");
new AlertDialog.Builder(activity)
.setTitle(boxResource.getResource("title").getValue())
.setMessage(exception.getMessage())
.setIcon(0)
.setPositiveButton(buttonResource.getResource(buttonKey).getValue(), action)
.create().show();
} else if (downloadBook) {
doDownloadBook(activity, book, false);
}
if (!mgr.mayBeAuthorised(true)) {
final NetworkLibrary library = NetworkLibrary.Instance();
library.invalidateVisibility();
library.synchronize();
}
if (NetworkView.Instance().isInitialized()) {
NetworkView.Instance().fireModelChangedAsync();
}
}
}; // end Handler
final Runnable runnable = new Runnable() {
public void run() {
ZLNetworkException exception = null;
try {
mgr.purchaseBook(book);
} catch (ZLNetworkException e) {
exception = e;
}
handler.sendMessage(handler.obtainMessage(0, exception));
}
}; // end Runnable
UIUtil.wait("purchaseBook", runnable, activity);
} // end onClick
}; // end listener
final Runnable buyRunnable = new Runnable() {
public void run() {
if (!mgr.needPurchase(book)) {
final ZLResource boxResource = dialogResource.getResource("alreadyPurchasedBox");
new AlertDialog.Builder(activity)
.setTitle(boxResource.getResource("title").getValue())
.setMessage(boxResource.getResource("message").getValue())
.setIcon(0)
.setPositiveButton(buttonResource.getResource("ok").getValue(), null)
.create().show();
return;
}
final ZLResource boxResource = dialogResource.getResource("purchaseConfirmBox");
new AlertDialog.Builder(activity)
.setTitle(boxResource.getResource("title").getValue())
.setMessage(boxResource.getResource("message").getValue().replace("%s", book.Title))
.setIcon(0)
.setPositiveButton(buttonResource.getResource("buy").getValue(), listener)
.setNeutralButton(buttonResource.getResource("buyAndDownload").getValue(), listener)
.setNegativeButton(buttonResource.getResource("cancel").getValue(), listener)
.create().show();
}
};
try {
if (mgr.isAuthorised(true)) {
buyRunnable.run();
return;
}
} catch (ZLNetworkException e) {
}
AuthenticationDialog.show(activity, book.Link, buyRunnable);
}
private static void doBuyInBrowser(Activity activity, final NetworkBookItem book) {
BookReference reference = book.reference(BookReference.Type.BUY_IN_BROWSER);
if (reference != null) {
Util.openInBrowser(activity, reference.URL);
}
}
}