package com.radicaldynamic.groupinform.activities;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import com.radicaldynamic.groupinform.R;
import com.radicaldynamic.groupinform.application.Collect;
import com.radicaldynamic.groupinform.logic.AccountFolder;
import com.radicaldynamic.groupinform.logic.InformOnlineState;
import com.radicaldynamic.groupinform.utilities.FileUtilsExtended;
import com.radicaldynamic.groupinform.utilities.HttpUtils;
public class AccountFolderReplicationList extends ListActivity
{
private final String t = "AccountFolderReplicationList: ";
public static final int SAVING_DIALOG = 0;
private AlertDialog mAlertDialog;
private ListView mListView;
private boolean mListChanged = false;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setTitle(getString(R.string.app_name) + " > " + getString(R.string.tf_synchronized_folders));
mListView = getListView();
mListView.setItemsCanFocus(false);
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
mListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3)
{
mListChanged = true;
}});
new RefreshViewTask().execute();
Toast.makeText(this, getString(R.string.tf_select_folders_for_offline_use), Toast.LENGTH_SHORT).show();
}
@Override
protected Dialog onCreateDialog(int id)
{
switch (id) {
case SAVING_DIALOG:
ProgressDialog saving = new ProgressDialog(this);
saving.setMessage(getText(R.string.tf_saving_please_wait));
saving.setIndeterminate(true);
saving.setCancelable(false);
return saving;
}
return null;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (mListChanged) {
showSaveDialog();
return true;
}
}
return super.onKeyDown(keyCode, event);
}
/*
* Refresh the main form browser view as requested by the user
*/
private class RefreshViewTask extends AsyncTask<Void, Void, Void>
{
private ArrayList<AccountFolder> folders = new ArrayList<AccountFolder>();
@Override
protected Void doInBackground(Void... nothing)
{
folders = AccountFolderList.loadFolderList();
return null;
}
@Override
protected void onPreExecute()
{
setProgressBarIndeterminateVisibility(true);
}
@Override
protected void onPostExecute(Void nothing)
{
if (folders.isEmpty()) {
// TODO: What now? This should never happen.
} else {
setListAdapter(new ArrayAdapter<AccountFolder>(
AccountFolderReplicationList.this,
android.R.layout.simple_list_item_multiple_choice,
folders));
// Check off items
for (int i = 0; i < mListView.getCount(); i++) {
boolean isReplicated = ((AccountFolder) mListView.getItemAtPosition(i)).isReplicated();
if (isReplicated)
mListView.setItemChecked(i, true);
else
mListView.setItemChecked(i, false);
}
}
setProgressBarIndeterminateVisibility(false);
}
}
// Send selections to update device record on server
private class UpdateReplicationsTask extends AsyncTask<Void, Void, String>
{
@Override
protected String doInBackground(Void... nothing)
{
// Get list of databases to replicate
List<String> databasesToReplicateById = new ArrayList<String>();
SparseBooleanArray checkedItemPositions = mListView.getCheckedItemPositions();
for (int i = 0; i < checkedItemPositions.size(); i++) {
if (checkedItemPositions.valueAt(i)) {
String databaseId = ((AccountFolder) mListView.getItemAtPosition(i)).getId();
if (Collect.Log.VERBOSE) Log.v(Collect.LOGTAG, t + "selected database " + databaseId + " for replication");
databasesToReplicateById.add(databaseId);
}
}
// Update device profile with list of databases to replicate
List<NameValuePair> params = new ArrayList<NameValuePair>();
for (int i = 0; i < databasesToReplicateById.size(); i++)
params.add(new BasicNameValuePair("databaseIds", databasesToReplicateById.get(i)));
String updateUrl = Collect.getInstance().getInformOnlineState().getServerUrl() + "/device/set/replications";
return HttpUtils.postUrlData(updateUrl, params);
}
@Override
protected void onPreExecute()
{
showDialog(SAVING_DIALOG);
}
@Override
protected void onPostExecute(String postResult)
{
removeDialog(SAVING_DIALOG);
JSONObject update;
try {
update = (JSONObject) new JSONTokener(postResult).nextValue();
String result = update.optString(InformOnlineState.RESULT, InformOnlineState.ERROR);
// Update successful
if (result.equals(InformOnlineState.OK)) {
Toast.makeText(getApplicationContext(), getString(R.string.tf_saved_data), Toast.LENGTH_SHORT).show();
// Force the list to refresh (do not be destructive in case something bad happens later)
new File(getCacheDir(), FileUtilsExtended.FOLDER_CACHE_FILE).setLastModified(0);
finish();
} else {
// Something bad happened
if (Collect.Log.ERROR) Log.e(Collect.LOGTAG, t + "system error while processing postResult");
Toast.makeText(getApplicationContext(), getString(R.string.tf_system_error_dialog_msg), Toast.LENGTH_LONG).show();
}
} catch (NullPointerException e) {
// Communication error
if (Collect.Log.ERROR) Log.e(Collect.LOGTAG, t + "no postResult to parse. Communication error with node.js server?");
Toast.makeText(getApplicationContext(), getString(R.string.tf_communication_error_try_again), Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (JSONException e) {
// Parse error (malformed result)
if (Collect.Log.ERROR) Log.e(Collect.LOGTAG, t + "failed to parse postResult " + postResult);
Toast.makeText(getApplicationContext(), getString(R.string.tf_system_error_dialog_msg), Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
}
private void showSaveDialog()
{
String[] items = {
getString(R.string.keep_changes),
getString(R.string.do_not_save)
};
mAlertDialog = new AlertDialog.Builder(this)
.setIcon(R.drawable.ic_dialog_alert)
.setTitle(getString(R.string.quit_application, "Without Saving?"))
.setNeutralButton(getString(R.string.do_not_exit), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id)
{
dialog.cancel();
}
})
.setItems(items,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which)
{
switch (which) {
case 0:
// Save and exit
new UpdateReplicationsTask().execute();
break;
case 1:
// Discard any changes and exit
finish();
break;
}
}
}).create();
mAlertDialog.show();
}
}