package com.quran.labs.androidquran.service.util;
import com.quran.labs.androidquran.R;
import com.quran.labs.androidquran.service.QuranDownloadService;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import java.lang.ref.WeakReference;
import java.text.DecimalFormat;
public class DefaultDownloadReceiver extends BroadcastReceiver {
private int mDownloadType = -1;
private SimpleDownloadListener mListener;
private ProgressDialog mProgressDialog;
private Context mContext = null;
private boolean mDidReceiveBroadcast;
private boolean mCanCancelDownload;
private static class DownloadReceiverHandler extends Handler {
private final WeakReference<DefaultDownloadReceiver> mReceiverRef;
public DownloadReceiverHandler(DefaultDownloadReceiver receiver) {
mReceiverRef = new WeakReference<>(receiver);
}
@Override
public void handleMessage(Message msg) {
final DefaultDownloadReceiver receiver = mReceiverRef.get();
if (receiver == null || receiver.mListener == null) {
return;
}
Intent intent = (Intent) msg.obj;
String state = intent.getStringExtra(
QuranDownloadNotifier.ProgressIntent.STATE);
switch (state) {
case QuranDownloadNotifier.ProgressIntent.STATE_SUCCESS:
receiver.dismissDialog();
receiver.mListener.handleDownloadSuccess();
break;
case QuranDownloadNotifier.ProgressIntent.STATE_ERROR: {
int msgId = ServiceIntentHelper.
getErrorResourceFromDownloadIntent(intent, true);
receiver.dismissDialog();
receiver.mListener.handleDownloadFailure(msgId);
break;
}
case QuranDownloadNotifier.ProgressIntent.STATE_DOWNLOADING: {
int progress = intent.getIntExtra(
QuranDownloadNotifier.ProgressIntent.PROGRESS, -1);
long downloadedSize = intent.getLongExtra(
QuranDownloadNotifier.ProgressIntent.DOWNLOADED_SIZE, -1);
long totalSize = intent.getLongExtra(
QuranDownloadNotifier.ProgressIntent.TOTAL_SIZE, -1);
int sura = intent.getIntExtra(QuranDownloadNotifier.ProgressIntent.SURA, -1);
int ayah = intent.getIntExtra(QuranDownloadNotifier.ProgressIntent.AYAH, -1);
if (receiver.mListener instanceof DownloadListener) {
((DownloadListener) receiver.mListener).updateDownloadProgress(progress,
downloadedSize, totalSize);
} else {
receiver.updateDownloadProgress(progress, downloadedSize, totalSize, sura, ayah);
}
break;
}
case QuranDownloadNotifier.ProgressIntent.STATE_PROCESSING: {
int progress = intent.getIntExtra(
QuranDownloadNotifier.ProgressIntent.PROGRESS, -1);
int processedFiles = intent.getIntExtra(
QuranDownloadNotifier.ProgressIntent.PROCESSED_FILES, 0);
int totalFiles = intent.getIntExtra(
QuranDownloadNotifier.ProgressIntent.TOTAL_FILES, 0);
if (receiver.mListener instanceof DownloadListener) {
((DownloadListener) receiver.mListener).updateProcessingProgress(progress,
processedFiles, totalFiles);
} else {
receiver.updateProcessingProgress(progress, processedFiles, totalFiles);
}
break;
}
case QuranDownloadNotifier.ProgressIntent
.STATE_ERROR_WILL_RETRY: {
int msgId = ServiceIntentHelper.
getErrorResourceFromDownloadIntent(intent, true);
if (receiver.mListener instanceof DownloadListener) {
((DownloadListener) receiver.mListener)
.handleDownloadTemporaryError(msgId);
} else {
receiver.handleNonFatalError(msgId);
}
break;
}
}
}
}
private final Handler mHandler;
public DefaultDownloadReceiver(Context context, int downloadType) {
mContext = context;
mDownloadType = downloadType;
mHandler = new DownloadReceiverHandler(this);
}
public void setCanCancelDownload(boolean canCancel) {
mCanCancelDownload = canCancel;
}
@Override
public void onReceive(Context context, Intent intent) {
if (intent == null) {
return;
}
int type = intent.getIntExtra(
QuranDownloadNotifier.ProgressIntent.DOWNLOAD_TYPE,
QuranDownloadService.DOWNLOAD_TYPE_UNDEF);
String state = intent.getStringExtra(
QuranDownloadNotifier.ProgressIntent.STATE);
if (mDownloadType != type || state == null) {
return;
}
mDidReceiveBroadcast = true;
Message msg = mHandler.obtainMessage();
msg.obj = intent;
// only care about the latest download progress
mHandler.removeCallbacksAndMessages(null);
// send the message at the front of the queue
mHandler.sendMessageAtFrontOfQueue(msg);
}
private void dismissDialog() {
if (mProgressDialog != null) {
try {
mProgressDialog.dismiss();
} catch (Exception e) {
// no op
}
mProgressDialog = null;
}
}
public boolean didReceiveBroadcast() {
return mDidReceiveBroadcast;
}
private void makeAndShowProgressDialog() {
makeProgressDialog();
if (mProgressDialog != null) {
mProgressDialog.show();
}
}
private void makeProgressDialog() {
if (mProgressDialog == null) {
mProgressDialog = new ProgressDialog(mContext);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(mCanCancelDownload);
if (mCanCancelDownload) {
mProgressDialog.setOnCancelListener(
new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
cancelDownload();
}
});
mProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
mContext.getString(R.string.cancel),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
cancelDownload();
}
});
}
mProgressDialog.setTitle(R.string.downloading_title);
mProgressDialog.setMessage(mContext.getString(
R.string.downloading_message));
}
}
private void cancelDownload() {
Intent i = new Intent(mContext, QuranDownloadService.class);
i.setAction(QuranDownloadService.ACTION_CANCEL_DOWNLOADS);
mContext.startService(i);
}
private void updateDownloadProgress(int progress,
long downloadedSize, long totalSize, int currentSura, int currentAyah) {
if (mProgressDialog == null) {
makeAndShowProgressDialog();
}
if (mProgressDialog != null) {
if (!mProgressDialog.isShowing()) {
mProgressDialog.show();
}
if (progress == -1) {
int titleId = R.string.downloading_title;
mProgressDialog.setIndeterminate(true);
mProgressDialog.setMessage(mContext.getString(titleId));
return;
}
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgress(progress);
DecimalFormat df = new DecimalFormat("###.00");
int mb = 1024 * 1024;
String downloaded = mContext.getString(R.string.prefs_megabytes_str,
df.format((1.0 * downloadedSize / mb)));
String total = mContext.getString(R.string.prefs_megabytes_str,
df.format((1.0 * totalSize / mb)));
String message;
if (currentSura < 1) {
message = String.format(
mContext.getString(R.string.download_progress),
downloaded, total);
} else if (currentAyah <= 0) {
message = String.format(
mContext.getString(R.string.download_sura_progress),
downloaded, total, currentSura);
} else {
message = String.format(mContext.getString(R.string.download_sura_ayah_progress),
currentSura, currentAyah);
}
mProgressDialog.setMessage(message);
}
}
private void updateProcessingProgress(int progress,
int processedFiles, int totalFiles) {
if (mProgressDialog == null) {
makeAndShowProgressDialog();
}
if (mProgressDialog != null) {
if (!mProgressDialog.isShowing()) {
mProgressDialog.show();
}
if (progress == -1) {
int titleId = R.string.extracting_title;
mProgressDialog.setIndeterminate(true);
mProgressDialog.setMessage(mContext.getString(titleId));
return;
}
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgress(progress);
mProgressDialog.setMessage(mContext.getString(R.string.extracting_title));
String message = String.format(
mContext.getString(R.string.process_progress),
processedFiles, totalFiles);
mProgressDialog.setMessage(message);
}
}
private void handleNonFatalError(int msgId) {
if (mProgressDialog == null) {
makeAndShowProgressDialog();
}
if (mProgressDialog != null) {
if (!mProgressDialog.isShowing()) {
mProgressDialog.show();
}
mProgressDialog.setMessage(mContext.getString(msgId));
}
}
public void setListener(SimpleDownloadListener listener) {
mListener = listener;
if (mListener == null && mProgressDialog != null) {
mProgressDialog.dismiss();
mProgressDialog = null;
} else if (mListener != null) {
makeProgressDialog();
}
}
public interface SimpleDownloadListener {
void handleDownloadSuccess();
void handleDownloadFailure(int errId);
}
public interface DownloadListener extends SimpleDownloadListener {
void updateDownloadProgress(int progress,
long downloadedSize, long totalSize);
void updateProcessingProgress(int progress,
int processFiles, int totalFiles);
void handleDownloadTemporaryError(int errorId);
}
}