/**
* ORcycle, Copyright 2014, 2015, PSU Transportation, Technology, and People Lab.
*
* @author Robin Murray <robin5@pdx.edu> (code)
* @author Miguel Figliozzi <figliozzi@pdx.edu> and ORcycle team (general app
* design and features, report questionnaires and new ORcycle features)
*
* For more information on the project, go to
* http://www.pdx.edu/transportation-lab/orcycle and http://www.pdx.edu/transportation-lab/app-development
*
* Updated/modified for Oregon pilot study and app deployment.
*
* ORcycle 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 3 of the License, or any later version.
* ORcycle 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
* ORcycle. If not, see <http://www.gnu.org/licenses/>.
*
*/
package edu.pdx.cecs.orcycle;
import java.util.ArrayList;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.database.SQLException;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.CursorAdapter;
import android.widget.ListView;
public class FragmentSavedNotesSection extends Fragment {
private static final String MODULE_TAG = "FragmentSavedNotesSection";
public static final String ARG_SECTION_NUMBER = "section_number";
ListView listSavedNotes;
ActionMode mActionModeNote;
ArrayList<Long> noteIdArray = new ArrayList<Long>();
private MenuItem saveMenuItemDelete, saveMenuItemUpload;
String[] values;
Long storedID;
Cursor allNotes;
public SavedNotesAdapter sna;
public FragmentSavedNotesSection() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = null;
try {
rootView = inflater.inflate(R.layout.activity_saved_notes, null);
Log.v(MODULE_TAG, "Cycle: SavedNotes onCreateView");
setHasOptionsMenu(true);
listSavedNotes = (ListView) rootView
.findViewById(R.id.listViewSavedNotes);
populateNoteList(listSavedNotes);
final DbAdapter mDb = new DbAdapter(getActivity());
mDb.open();
try {
// Clean up any bad notes from crashes
int cleanedNotes = mDb.cleanNoteTables();
/* if (cleanedNotes > 0) {
Toast.makeText(getActivity(),
"" + cleanedNotes + " bad notes(s) removed.",
Toast.LENGTH_SHORT).show();
} */
}
finally {
mDb.close();
}
noteIdArray.clear();
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
return rootView;
}
private final ActionMode.Callback mActionModeCallbackNote = new ActionMode.Callback() {
// Called when the action mode is created; startActionMode() was called
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
try {
// Inflate a menu resource providing context menu items
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.saved_notes_context_menu, menu);
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
return true;
}
// Called each time the action mode is shown. Always called after
// onCreateActionMode, but
// may be called multiple times if the mode is invalidated.
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
try {
Log.v(MODULE_TAG, "Prepare");
saveMenuItemDelete = menu.getItem(0);
saveMenuItemDelete.setEnabled(false);
saveMenuItemUpload = menu.getItem(1);
int flag = 1;
for (int i = 0; i < listSavedNotes.getCount(); i++) {
allNotes.moveToPosition(i);
flag = flag
* (allNotes.getInt(allNotes
.getColumnIndex("notestatus")) - 1);
if (flag == 0) {
storedID = allNotes.getLong(allNotes.getColumnIndex("_id"));
Log.v(MODULE_TAG, "" + storedID);
break;
}
}
if (flag == 1) {
saveMenuItemUpload.setEnabled(false);
} else {
saveMenuItemUpload.setEnabled(true);
}
mode.setTitle(noteIdArray.size() + " Selected");
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
return false; // Return false if nothing is done
}
// Called when the user selects a contextual menu item
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
try {
switch (item.getItemId()) {
case R.id.action_delete_saved_notes:
try {
// delete selected notes
for (int i = 0; i < noteIdArray.size(); i++) {
deleteNote(noteIdArray.get(i));
}
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
mode.finish(); // Action picked, so close the CAB
return true;
case R.id.action_upload_saved_notes:
try {
// upload selected notes
// for (int i = 0; i < noteIdArray.size(); i++) {
// retryNoteUpload(noteIdArray.get(i));
// }
// Log.v("Jason", "" + storedID);
retryNoteUpload(storedID);
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
return false;
}
// Called when the user exits the action mode
@Override
public void onDestroyActionMode(ActionMode mode) {
try {
int numListViewItems = listSavedNotes.getChildCount();
mActionModeNote = null;
noteIdArray.clear();
// Reset all list items to their normal color
for (int i = 0; i < numListViewItems; i++) {
listSavedNotes.getChildAt(i).setBackgroundColor(Color.parseColor("#80ffffff"));
}
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
}
};
void populateNoteList(ListView lv) {
// Get list from the real phone database. W00t!
final DbAdapter mDb = new DbAdapter(getActivity());
//mDb.open();
mDb.openReadOnly();
try {
allNotes = mDb.fetchAllNotes();
Log.e(MODULE_TAG, "------------------> populateNoteList()");
String[] from = new String[] { "noteseverity", "noterecorded" };
int[] to = new int[] { R.id.tvSnliNoteSeverity, R.id.tvSnliRecorded };
sna = new SavedNotesAdapter(getActivity(),
R.layout.saved_notes_list_item, allNotes, from, to,
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
lv.setAdapter(sna);
} catch (SQLException ex) {
Log.e(MODULE_TAG, ex.getMessage());
// Do nothing, for now!
} catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
mDb.close();
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int pos, long noteId) {
Log.v(MODULE_TAG, "onItemClick (id = " + String.valueOf(noteId) + ", pos = " + String.valueOf(pos) + ")");
try {
if (mActionModeNote == null) {
// If the note has just been recently scheduled, we won't ask the user
// if they want to upload it. This fixes a bug whereby the note is
// in the process of uploading, but the user wants to see it now.
if (NoteUploader.isPending(noteId)) {
transitionToNoteMapActivity(noteId);
}
else {
final DbAdapter mDb = new DbAdapter(getActivity());
mDb.openReadOnly();
try {
int noteStatus = mDb.getNoteStatus(noteId);
if (noteStatus == 2) {
transitionToNoteMapActivity(noteId);
} else if (noteStatus == 1) {
buildAlertMessageUnuploadedNoteClicked(noteId);
}
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
finally {
mDb.close();
}
}
} else {
// highlight
if (noteIdArray.indexOf(noteId) > -1) {
noteIdArray.remove(noteId);
v.setBackgroundColor(Color.parseColor("#80ffffff"));
} else {
noteIdArray.add(noteId);
v.setBackgroundColor(Color.parseColor("#ff33b5e5"));
}
// Toast.makeText(getActivity(), "Selected: " + noteIdArray,
// Toast.LENGTH_SHORT).show();
if (noteIdArray.size() == 0) {
saveMenuItemDelete.setEnabled(false);
} else {
saveMenuItemDelete.setEnabled(true);
}
mActionModeNote.setTitle(noteIdArray.size() + " Selected");
}
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
}
});
registerForContextMenu(lv);
}
private void buildAlertMessageUnuploadedNoteClicked(final long position) {
try {
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Upload Note");
builder.setMessage("Do you want to upload this note?");
builder.setNegativeButton("Upload",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
try {
dialog.cancel();
retryNoteUpload(position);
// Toast.makeText(getActivity(),"Send Clicked: "+position,
// Toast.LENGTH_SHORT).show();
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
}
});
builder.setPositiveButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
try {
dialog.cancel();
// continue
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
}
});
final AlertDialog alert = builder.create();
alert.show();
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
}
private void retryNoteUpload(long noteId) {
NoteUploader uploader = new NoteUploader(getActivity(), MyApplication.getInstance().getUserId());
FragmentSavedNotesSection f3 = (FragmentSavedNotesSection) getActivity()
.getSupportFragmentManager().findFragmentByTag(
"android:switcher:" + R.id.pager + ":2");
uploader.setSavedNotesAdapter(sna);
uploader.setFragmentSavedNotesSection(f3);
uploader.setListView(listSavedNotes);
uploader.execute();
}
private void deleteNote(long noteId) {
DbAdapter mDbHelper = new DbAdapter(getActivity());
mDbHelper.open();
try {
mDbHelper.deleteNote(noteId);
}
finally {
mDbHelper.close();
}
listSavedNotes.invalidate();
populateNoteList(listSavedNotes);
}
// show edit button and hidden delete button
@Override
public void onResume() {
super.onResume();
try {
Log.v(MODULE_TAG, "Cycle: SavedNotes onResume");
listSavedNotes.invalidate();
populateNoteList(listSavedNotes);
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
}
@Override
public void onPause() {
super.onPause();
try {
Log.v(MODULE_TAG, "Cycle: SavedNotes onPause");
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
try {
Log.v(MODULE_TAG, "Cycle: SavedNotes onDestroyView");
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
}
/* Creates the menu items */
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
try {
// Inflate the menu items for use in the action bar
inflater.inflate(R.menu.saved_notes, menu);
super.onCreateOptionsMenu(menu, inflater);
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
}
/* Handles item selections */
@Override
public boolean onOptionsItemSelected(MenuItem item) {
try {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_edit_saved_notes:
// edit
if (mActionModeNote != null) {
return false;
}
// Start the CAB using the ActionMode.Callback defined above
mActionModeNote = getActivity().startActionMode(
mActionModeCallbackNote);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
return false;
}
private void transitionToNoteMapActivity(long noteId) {
Intent intent = new Intent(getActivity(), NoteMapActivity.class);
intent.putExtra(NoteMapActivity.EXTRA_NOTE_ID, noteId);
startActivity(intent);
getActivity().overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
getActivity().finish();
}
}