package com.radicaldynamic.gcmobile.android.activities;
import java.util.HashMap;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import com.radicaldynamic.groupinform.R;
import com.radicaldynamic.groupinform.activities.FormEntryActivity;
import com.radicaldynamic.groupinform.application.Collect;
import com.radicaldynamic.groupinform.documents.FormDefinition;
import com.radicaldynamic.groupinform.listeners.DataExportListener;
import com.radicaldynamic.groupinform.tasks.DataExportTask;
public class DataExportActivity extends Activity implements DataExportListener
{
private static final String t = "DataExportActivity: ";
// For use with mProgressHandler
public static final String KEY_PROGRESS_MSG = "progress_msg";
// Export options
public static final String KEY_EXPORT_DRAFT = "export_draft";
public static final String KEY_EXPORT_COMPLETED = "export_complete";
public static final String KEY_OUTPUT_EXTERNAL = "output_external";
public static final String KEY_OUTPUT_SEND = "output_send";
public static final String KEY_OUTPUT_ZIP = "external_zip";
public static final String KEY_OUTPUT_MEDIA_FILES = "output_media_files";
public static final String KEY_OUTPUT_XFORM_FILES = "output_xform_files";
public static final String KEY_OUTPUT_RECORD_METADATA = "output_record_metadata";
// For handling activity restarts
private static final String KEY_DATA_EXPORT_TASK = "data_export_task";
private static final String KEY_FORM_DEFINITION = "form_definition";
private static final int DIALOG_DEFINITION_UNAVAILABLE = 1;
private static final int DIALOG_EMAIL_DEPENDENCY = 2;
private static final int DIALOG_NO_SEND_ACTIVITY = 3;
private static final int DIALOG_OPTIONS_REQUIRED = 4;
private Dialog mDialog;
private ProgressDialog mProgressDialog;
private DataExportTask mDataExportTask;
private CheckBox mExportDraft;
private CheckBox mExportCompleted;
private CheckBox mOutputExternal;
private CheckBox mOutputSend;
private CheckBox mOutputZip;
private CheckBox mOutputMediaFiles;
private CheckBox mOutputXFormFiles;
private CheckBox mOutputRecordMetadata;
private FormDefinition mFormDefinition;
private Handler mProgressHandler = new Handler() {
@Override
public void handleMessage(Message msg)
{
switch (msg.what) {
case DataExportTask.ERROR:
AlertDialog.Builder builder = new AlertDialog.Builder(DataExportActivity.this);
// TODO: write or pass a proper error message
builder.setMessage(DataExportActivity.this.getString(R.string.tf_unknown_error))
.setCancelable(false)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
});
AlertDialog alert = builder.create();
alert.show();
break;
case DataExportTask.PROGRESS:
Bundle data = msg.getData();
mProgressDialog.setMessage(data.getString(KEY_PROGRESS_MSG));
break;
case DataExportTask.COMPLETE:
mProgressDialog.dismiss();
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.data_export);
mExportDraft = (CheckBox) findViewById(R.id.exportDraft);
mExportCompleted = (CheckBox) findViewById(R.id.exportCompleted);
mOutputExternal = (CheckBox) findViewById(R.id.outputExternal);
mOutputSend = (CheckBox) findViewById(R.id.outputSend);
mOutputZip = (CheckBox) findViewById(R.id.outputZip);
mOutputMediaFiles = (CheckBox) findViewById(R.id.outputMediaFiles);
mOutputXFormFiles = (CheckBox) findViewById(R.id.outputXFormFiles);
mOutputRecordMetadata = (CheckBox) findViewById(R.id.outputRecordMetadata);
Button beginExport = (Button) findViewById(R.id.beginExport);
beginExport.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v)
{
if (!verifyFilterOptions() || !verifyDestionationOptions()) {
showDialog(DIALOG_OPTIONS_REQUIRED);
} else {
mProgressDialog = new ProgressDialog(DataExportActivity.this);
mProgressDialog.setCancelable(false);
mProgressDialog.setMessage(getString(R.string.tf_preparing_to_export));
mProgressDialog.show();
new Thread() {
public void run() {
try {
mDataExportTask = new DataExportTask();
mDataExportTask.setDataExportListener(DataExportActivity.this);
mDataExportTask.execute(mProgressHandler, mFormDefinition, getExportOptions());
} catch (Exception e) {
e.printStackTrace();
mProgressDialog.dismiss();
mProgressHandler.sendMessage(mProgressHandler.obtainMessage(DataExportTask.ERROR));
}
}
}.start();
}
}
});
// Handle dependencies
mOutputExternal.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (!mOutputSend.isChecked()) {
mOutputZip.setEnabled(isChecked);
mOutputMediaFiles.setEnabled(isChecked);
mOutputXFormFiles.setEnabled(isChecked);
mOutputRecordMetadata.setEnabled(isChecked);
}
if (!mOutputMediaFiles.isChecked() && isChecked)
mOutputMediaFiles.setChecked(true);
if (!mOutputRecordMetadata.isChecked() && isChecked)
mOutputRecordMetadata.setChecked(true);
}
});
// Handle dependencies
mOutputSend.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (!mOutputExternal.isChecked()) {
mOutputZip.setEnabled(isChecked);
mOutputMediaFiles.setEnabled(isChecked);
mOutputXFormFiles.setEnabled(isChecked);
mOutputRecordMetadata.setEnabled(isChecked);
}
if (!mOutputZip.isChecked() && isChecked)
mOutputZip.setChecked(true);
if (!mOutputMediaFiles.isChecked() && isChecked)
mOutputMediaFiles.setChecked(true);
if (!mOutputRecordMetadata.isChecked() && isChecked)
mOutputRecordMetadata.setChecked(true);
}
});
// Handle dependencies
mOutputZip.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (!isChecked) {
if (mOutputSend.isChecked()) {
showDialog(DIALOG_EMAIL_DEPENDENCY);
mOutputZip.setChecked(true);
}
}
}
});
Object data = getLastNonConfigurationInstance();
if (data instanceof HashMap<?, ?>) {
// Continue data export
if (((HashMap<?, ?>) data).containsKey(KEY_DATA_EXPORT_TASK)) {
// Recreate progress handler for UI
mProgressDialog = new ProgressDialog(DataExportActivity.this);
mProgressDialog.setCancelable(false);
mProgressDialog.setMessage("Resuming export...");
mProgressDialog.show();
mDataExportTask = (DataExportTask) ((HashMap<?, ?>) data).get(KEY_DATA_EXPORT_TASK);
mDataExportTask.setHandler(mProgressHandler);
}
// Save us refetching from the database
if (((HashMap<?, ?>) data).containsKey(KEY_FORM_DEFINITION)) {
mFormDefinition = (FormDefinition) ((HashMap<?, ?>) data).get(KEY_FORM_DEFINITION);
}
} else {
Intent intent = getIntent();
if (intent == null) {
// Defaults?
} else {
String id = intent.getStringExtra(FormEntryActivity.KEY_FORMPATH);
try {
mFormDefinition = Collect.getInstance().getDbService().getDb().get(FormDefinition.class, id);
} catch (Exception e ){
if (Collect.Log.ERROR) Log.e(Collect.LOGTAG, t + "unexpected exception while retrieving form definition document: " + e.toString());
e.printStackTrace();
showDialog(DIALOG_DEFINITION_UNAVAILABLE);
}
}
}
if (mFormDefinition != null) {
setTitle(getString(R.string.app_name) + " > " + getString(R.string.tf_export_from) + " " + mFormDefinition.getName());
}
}
public Dialog onCreateDialog(int id)
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
mDialog = null;
switch (id) {
case DIALOG_DEFINITION_UNAVAILABLE:
builder
.setCancelable(false)
.setIcon(R.drawable.ic_dialog_info)
.setTitle(R.string.tf_unable_to_load_instances_dialog)
.setMessage(R.string.tf_unable_to_load_instances_dialog_msg);
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
finish();
}
});
mDialog = builder.create();
break;
case DIALOG_EMAIL_DEPENDENCY:
builder
.setCancelable(false)
.setIcon(R.drawable.ic_dialog_info)
.setTitle(R.string.tf_unable_to_export_send_dependency)
.setMessage(R.string.tf_unable_to_export_send_dependency_msg);
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
mDialog = builder.create();
break;
case DIALOG_NO_SEND_ACTIVITY:
builder
.setCancelable(false)
.setIcon(R.drawable.ic_dialog_info)
.setTitle(R.string.tf_unable_to_send_export)
.setMessage(R.string.tf_unable_to_send_export_msg);
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
mDialog = builder.create();
break;
case DIALOG_OPTIONS_REQUIRED:
builder
.setCancelable(false)
.setIcon(R.drawable.ic_dialog_alert)
.setTitle(R.string.tf_unable_to_export_data_missing_options_dialog)
.setMessage(R.string.tf_unable_to_export_data_missing_options_dialog_msg);
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
mDialog = builder.create();
break;
}
return mDialog;
}
@Override
public void onPause()
{
super.onPause();
if (mProgressDialog != null && mProgressDialog.isShowing())
mProgressDialog.cancel();
}
@Override
public Object onRetainNonConfigurationInstance()
{
HashMap<String, Object> data = new HashMap<String, Object>();
// If an export task is running, pass it to the next thread
if (mDataExportTask != null && mDataExportTask.getStatus() != AsyncTask.Status.FINISHED)
data.put(KEY_DATA_EXPORT_TASK, mDataExportTask);
if (mFormDefinition != null)
data.put(KEY_FORM_DEFINITION, mFormDefinition);
return data;
}
@Override
public void exportComplete(final Bundle data)
{
final String tt = t + "exportComplete(): ";
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder
.setCancelable(false)
.setIcon(R.drawable.ic_dialog_info)
.setTitle("Export Successful")
.setMessage(data.getString(DataExportListener.KEY_MESSAGE));
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
mOutputSend = (CheckBox) findViewById(R.id.outputSend);
if (mOutputSend.isChecked()) {
builder.setNeutralButton(getString(R.string.tf_send), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String attachment = "file://" + data.getString(DataExportListener.KEY_EMAIL_ATTACHMENT);
if (Collect.Log.DEBUG) Log.d(Collect.LOGTAG, tt + "Path to exported attachment is " + attachment);
try {
Intent i = new Intent(Intent.ACTION_SEND);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
i.setType("application/zip");
i.putExtra(Intent.EXTRA_STREAM, Uri.parse(attachment));
startActivity(i);
} catch (ActivityNotFoundException e) {
dialog.cancel();
showDialog(DIALOG_NO_SEND_ACTIVITY);
}
}
});
}
mDialog = builder.create();
mDialog.show();
}
@Override
public void exportError(String errorMsg)
{
// Close progress automatically
if (mProgressDialog != null && mProgressDialog.isShowing())
mProgressDialog.dismiss();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder
.setCancelable(false)
.setIcon(R.drawable.ic_dialog_alert)
.setTitle("Export Problem")
.setMessage(errorMsg);
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
mDialog = builder.create();
mDialog.show();
}
/*
* Examine all output option controls and set a bundle that will represent options
* selected. Bundle will be passed to export task.
*/
private Bundle getExportOptions()
{
Bundle data = new Bundle();
if (mExportDraft.isChecked())
data.putBoolean(KEY_EXPORT_DRAFT, true);
if (mExportCompleted.isChecked())
data.putBoolean(KEY_EXPORT_COMPLETED, true);
if (mOutputExternal.isEnabled() && mOutputExternal.isChecked())
data.putBoolean(KEY_OUTPUT_EXTERNAL, true);
if (mOutputSend.isEnabled() && mOutputSend.isChecked()) {
data.putBoolean(KEY_OUTPUT_SEND, true);
}
if (mOutputZip.isEnabled() && mOutputZip.isChecked())
data.putBoolean(KEY_OUTPUT_ZIP, true);
if (mOutputMediaFiles.isEnabled() && mOutputMediaFiles.isChecked())
data.putBoolean(KEY_OUTPUT_MEDIA_FILES, true);
if (mOutputXFormFiles.isEnabled() && mOutputXFormFiles.isChecked())
data.putBoolean(KEY_OUTPUT_XFORM_FILES, true);
if (mOutputRecordMetadata.isEnabled() && mOutputRecordMetadata.isChecked())
data.putBoolean(KEY_OUTPUT_RECORD_METADATA, true);
return data;
}
/*
* Ensure that at least one output option is selected
*/
private boolean verifyDestionationOptions()
{
if (mOutputExternal.isChecked() || mOutputSend.isChecked())
return true;
return false;
}
/*
* Ensure that at least one filter option is selected
*/
private boolean verifyFilterOptions()
{
if (mExportDraft.isChecked() || mExportCompleted.isChecked())
return true;
return false;
}
}