package info.guardianproject.securereaderinterface.ui;
import info.guardianproject.securereaderinterface.R;
import info.guardianproject.securereader.SocialReader;
import info.guardianproject.securereaderinterface.AddFeedActivity;
import info.guardianproject.securereaderinterface.AddPostActivity;
import info.guardianproject.securereaderinterface.App;
import info.guardianproject.securereaderinterface.CreateAccountActivity;
import info.guardianproject.securereaderinterface.DownloadEpubReaderActivity;
import info.guardianproject.securereaderinterface.DownloadsActivity;
import info.guardianproject.securereaderinterface.FragmentActivityWithMenu;
import info.guardianproject.securereaderinterface.HelpActivity;
import info.guardianproject.securereaderinterface.MainActivity;
import info.guardianproject.securereaderinterface.PostActivity;
import info.guardianproject.securereaderinterface.SettingsActivity;
import info.guardianproject.securereaderinterface.ViewMediaActivity;
import info.guardianproject.securereaderinterface.installer.HTTPDAppSender;
import info.guardianproject.securereaderinterface.installer.SecureBluetooth;
import info.guardianproject.securereaderinterface.installer.SecureBluetoothReceiverActivity;
import info.guardianproject.securereaderinterface.models.FeedFilterType;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.holoeverywhere.widget.Toast;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import com.tinymission.rss.Feed;
import com.tinymission.rss.Item;
import com.tinymission.rss.MediaContent;
public class UICallbacks
{
public enum RequestCode
{
BT_ENABLE(SecureBluetooth.REQUEST_ENABLE_BT),
BT_DISCOVERABLE(SecureBluetooth.REQUEST_ENABLE_BT_DISCOVERY),
CREATE_CHAT_ACCOUNT(20);
/**
* Value for this RequestCode
*/
public final int Value;
private RequestCode(int value)
{
Value = value;
}
static void checkUniqueness()
{
ArrayList<Integer> intvals = new ArrayList<Integer>();
for (RequestCode code : RequestCode.values())
{
if (intvals.contains(code.Value))
throw new RuntimeException("RequestCode array is invalid (not usnique numbers), check the values!");
intvals.add(code.Value);
}
}
};
public interface OnCallbackListener
{
/*
* Called when the feed filter should change to only show the selected
* feed (or all feeds if the flag is set)
*
* This may occur either when a feed is selected in the feed drop down
* or when the source feed of a story item in the stream is clicked.
*/
void onFeedSelect(FeedFilterType type, long feedId, Object source);
/* Called to filter on a special tag */
void onTagSelect(String tag);
void onRequestResync(Feed feed);
/**
* Called when an item has been marked/unmarked as a favorite. Affects
* our list of favorites.
*/
void onItemFavoriteStatusChanged(Item item);
/**
* Called to handle a command.
*/
void onCommand(int command, Bundle commandParameters);
}
private static UICallbacks gInstance;
public static UICallbacks getInstance()
{
if (gInstance == null)
gInstance = new UICallbacks();
return gInstance;
}
private final ArrayList<OnCallbackListener> mListeners;
private UICallbacks()
{
mListeners = new ArrayList<OnCallbackListener>();
RequestCode.checkUniqueness();
}
public void addListener(OnCallbackListener listener)
{
synchronized (mListeners)
{
if (!mListeners.contains(listener))
mListeners.add(listener);
}
}
public void removeListener(OnCallbackListener listener)
{
synchronized (mListeners)
{
if (mListeners.contains(listener))
mListeners.remove(listener);
}
}
public static void setFeedFilter(FeedFilterType type, long feedId, Object source)
{
getInstance().fireCallback("onFeedSelect", type, feedId, source);
}
public static void requestResync(Feed feed)
{
getInstance().fireCallback("onRequestResync", feed);
}
public static void setTagFilter(String tag, Object source)
{
getInstance().fireCallback("onTagSelect", tag);
}
public static void itemFavoriteStatusChanged(Item item)
{
getInstance().fireCallback("onItemFavoriteStatusChanged", item);
}
private void fireCallback(String methodName, Object... commandParameters)
{
Class<?>[] paramTypes = null;
try
{
// Figure out what types we need for the call
Method[] interfaceMethods = OnCallbackListener.class.getMethods();
for (Method interfaceMethod : interfaceMethods)
{
if (interfaceMethod.getName().equals(methodName))
{
paramTypes = interfaceMethod.getParameterTypes();
break;
}
}
synchronized (mListeners)
{
for (int i = 0; i < mListeners.size(); i++)
{
OnCallbackListener listener = mListeners.get(i);
try
{
Method m = listener.getClass().getMethod(methodName, paramTypes);
m.invoke(listener, commandParameters);
}
catch (Exception ex)
{
// TODO - remove listener?
}
}
}
}
catch (Exception ex)
{
Log.d(MainActivity.LOGTAG, "Failed to get callback method info: " + ex.toString());
}
}
public static void handleCommand(Context context, int command, Bundle commandParameters)
{
getInstance().fireCallback("onCommand", command, commandParameters);
switch (command)
{
case R.integer.command_news_list:
{
Intent intent = new Intent(context, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
break;
}
case R.integer.command_posts_list:
{
Intent intent = new Intent(context, PostActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
if (commandParameters != null && commandParameters.containsKey("go_to_tab"))
{
intent.putExtra("go_to_tab", commandParameters.getInt("go_to_tab", -1));
}
context.startActivity(intent);
break;
}
case R.integer.command_post_add:
{
Intent intent = new Intent(context, AddPostActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
((Activity) context).overridePendingTransition(R.anim.slide_in_from_right, R.anim.slide_out_to_left);
break;
}
case R.integer.command_feed_add:
{
Intent intent = new Intent(context, AddFeedActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
((Activity) context).overridePendingTransition(R.anim.slide_in_from_right, R.anim.slide_out_to_left);
break;
}
case R.integer.command_settings:
{
Intent intent = new Intent(context, SettingsActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
break;
}
case R.integer.command_toggle_online:
{
if (App.getInstance().socialReader.isOnline() == SocialReader.NOT_ONLINE_NO_TOR)
App.getInstance().socialReader.connectTor((Activity) context);
// else
// Not sure this makes sense
// App.getInstance().socialReader.goOffline();
break;
}
case R.integer.command_view_media:
{
Log.v("UICallbacks", "command_view_media");
if (commandParameters != null && commandParameters.containsKey("media"))
{
MediaContent mediaContent = (MediaContent) commandParameters.getSerializable("media");
Log.v("UICallbacks", "MediaContent " + mediaContent.getType());
if (mediaContent != null && mediaContent.getType().startsWith("application/vnd.android.package-archive"))
{
// This is an application package. View means
// "ask for installation"...
if (mediaContent.getDownloadedNonVFSFile() != null) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.fromFile(mediaContent.getDownloadedNonVFSFile()),mediaContent.getType());
context.startActivity(intent);
}
}
else if (mediaContent != null && mediaContent.getType().startsWith("application/epub+zip"))
{
Log.v("UICallbacks", "MediaContent is epub");
// This is an epub
if (mediaContent.getDownloadedNonVFSFile() != null) {
Log.v("UICallbacks", "Not null");
try {
File properlyNamed = new File(mediaContent.getDownloadedNonVFSFile().toString() + ".epub");
InputStream in = new FileInputStream(mediaContent.getDownloadedNonVFSFile());
OutputStream out = new FileOutputStream(properlyNamed);
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(properlyNamed),mediaContent.getType());
PackageManager packageManager = context.getPackageManager();
List list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (list.size() > 0) {
Log.v("UICallbacks", "Launching epub reader" + Uri.fromFile(properlyNamed).toString());
context.startActivity(intent);
}
else {
Log.v("UICallbacks", "No application found" + Uri.fromFile(properlyNamed).toString());
// Download epub reader?
int numShown = App.getSettings().downloadEpubReaderDialogShown();
if (numShown < 1)
{
App.getSettings().setDownloadEpubReaderDialogShown(numShown + 1);
intent = new Intent(context, DownloadEpubReaderActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
((Activity) context).overridePendingTransition(R.anim.slide_in_from_right, R.anim.slide_out_to_left);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else {
Log.v("UICallbacks", "NULL");
}
}
else
{
Intent intent = new Intent(context, ViewMediaActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("parameters", commandParameters);
context.startActivity(intent);
}
}
else
{
Log.e(MainActivity.LOGTAG, "Invalid parameters to command command_view_media.");
}
break;
}
case R.integer.command_chat:
{
// If we don't have an account yet, we need to create that!
if (!PackageHelper.isChatSecureInstalled(context))
{
int numShown = App.getSettings().chatSecureDialogShown();
if (numShown < 2)
{
AlertDialog dialog = PackageHelper.showDownloadDialog(context, R.string.install_chat_secure_title, R.string.install_chat_secure_prompt,
android.R.string.ok, android.R.string.cancel, PackageHelper.URI_CHATSECURE_PLAY);
App.getSettings().setChatSecureDialogShown(numShown + 1);
}
else
{
// Stop prompting, just show a toast with info
Toast.makeText(context, R.string.install_chat_secure_toast, Toast.LENGTH_SHORT).show();
}
}
else if (App.getInstance().socialReporter.getAuthorName() == null)
{
Intent intent = new Intent(context, CreateAccountActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
((Activity) context).overridePendingTransition(R.anim.slide_in_from_right, R.anim.slide_out_to_left);
}
else
{
/*
if (!App.getSettings().chatUsernamePasswordSet()
&& App.getInstance().socialReader.ssettings.getChatSecureUsername() != null
&& App.getInstance().socialReader.ssettings.getChatSecurePassword() != null) {
*/
/*
ima://foo:pass@bar.com/
action = android.intent.action.INSERT
*/
/*
Intent usernamePasswordIntent = new Intent(Intent.ACTION_INSERT,
Uri.parse("ima://"+App.getInstance().socialReader.ssettings.getXMLRPCUsername()+":"
+App.getInstance().socialReader.ssettings.getXMLRPCPassword()+"@dukgo.com/"));
*/
//context.startActivity(usernamePasswordIntent);
//((FragmentActivityWithMenu) context).startActivityForResultAsInternal(usernamePasswordIntent, RequestCode.CREATE_CHAT_ACCOUNT.Value);
// How to tell if it worked?
//((Activity)context).startActivityForResult(usernamePasswordIntent,REGISTER_CHAT_USERNAME_PASSWORD);
// if it is OK then App.getSettings().setChatUsernamePasswordSet();
/*
} else if (App.getInstance().socialReader.ssettings.getChatSecurePassword() == null ||
App.getInstance().socialReader.ssettings.getChatSecureUsername() == null) {
*/
// Register Social Reporter username/password
/*} else {*/
Log.v("UICallbacks", "Start the chat application now!");
String roomName = context.getString(R.string.chatroom_name);
if (commandParameters != null && commandParameters.containsKey("room_name"))
roomName = commandParameters.getString("room_name");
if (roomName == null)
roomName = "";
Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("immu://" + App.getInstance().socialReporter.getAuthorName()
+ "@conference.dukgo.com/" + roomName));
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
if (!PackageHelper.canIntentBeHandled(context, intent))
{
// Old version of ChatSecure that don't support intent API.
// Need to upgrade!
AlertDialog dialog = PackageHelper.showDownloadDialog(context, R.string.install_chat_secure_title,
R.string.install_chat_secure_prompt_upgrade, android.R.string.ok, android.R.string.cancel, PackageHelper.URI_CHATSECURE_PLAY);
}
else
{
context.startActivity(intent);
}
/*}*/
}
break;
}
case R.integer.command_downloads:
{
Intent intent = new Intent(context, DownloadsActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
((Activity) context).overridePendingTransition(R.anim.slide_in_from_right, R.anim.slide_out_to_left);
break;
}
case R.integer.command_help:
{
Intent intent = new Intent(context, HelpActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
((Activity) context).overridePendingTransition(R.anim.slide_in_from_right, R.anim.slide_out_to_left);
break;
}
case R.integer.command_receiveshare:
{
Log.v("UICallbacks", "Calling receive share activity");
Intent intent = new Intent(context, SecureBluetoothReceiverActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
((Activity) context).overridePendingTransition(R.anim.slide_in_from_right, R.anim.slide_out_to_left);
break;
}
case R.integer.command_shareapp:
{
Log.v("UICallbacks", "Calling HTTPDAppSender");
Intent intent = new Intent(context, HTTPDAppSender.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
((Activity) context).overridePendingTransition(R.anim.slide_in_from_right, R.anim.slide_out_to_left);
break;
}
}
}
}