package net.bradmont.openmpd.fragments;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ClipDrawable;
import android.graphics.PorterDuff.Mode;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.ViewGroup;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.SimpleCursorAdapter;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.PopupMenu;
import android.widget.TextView;
import android.support.v4.app.Fragment;
import android.support.v4.app.ListFragment;
import android.util.TypedValue;
import net.bradmont.openmpd.helpers.Log;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import net.bradmont.openmpd.models.*;
import net.bradmont.openmpd.activities.ContactDetailActivity;
import net.bradmont.openmpd.helpers.TextTools;
import net.bradmont.openmpd.*;
import net.bradmont.openmpd.views.EnhancedListView;
public class NotificationsFragment extends ListFragment{
private EnhancedListAdapter mAdapter;
private EnhancedListView mListView;
private OnClickListener mOnClickListener = null;
private final static String NOTIFICATIONS_QUERY =
"select notification._id, notification.contact_id, notification.type, notification.status, notification.message, notification.date, notification.last_gift, notification.giving_amount, notification.partner_type, notification.partner_status, contact.*, contact_status.status as contact_status, contact_status.partner_type, contact_status.giving_amount, contact_status.manual_set_expires, contact_status.gift_frequency, spouse.fname as spouse_fname, spouse.lname as spouse_lname from notification left join contact on notification.contact_id = contact._id left join contact_status on contact._id=contact_status.contact_id left outer join contact as spouse on contact.spouse_id=spouse._id where notification.status = ? and not (type = 2 and contact_status = 5 and manual_set_expires > date) and not (notification.partner_type < 10 and notification.partner_type > 0) and not (contact_Status = 5 and message = 4) order by date desc;";
// and not (type = 2 and contact_status = 5 and manual_set_expires > date)
// filters out "Continued" notifications for donors set as regular by
// the user
// and not (0 < partner_type < 10) is to weed out old notifications from a previous app version
// and not (contact_status = "5" and message="4") weeds out notification change from "new" to "current"
private static final String [] columns = { "lname", "giving_amount", "type", "fname", "fname", "spouse_fname", "date", "type"};
private static final int [] fields = { R.id.name, R.id.amount, R.id.type, R.id.initials, R.id.user_icon_left, R.id.user_icon_right, R.id.date, R.id.quickactions};
private static int[] icon_colors = null;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mListView = (EnhancedListView) inflater.inflate(R.layout.enhancedlist, null);
setHasOptionsMenu(true);
return mListView;
}
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
icon_colors = getActivity().getResources().getIntArray(R.array.user_icon_colors);
Cursor cursor = MPDDBHelper.get().getReadableDatabase()
.rawQuery(NOTIFICATIONS_QUERY,
new String [] { Integer.toString(Notification.STATUS_NOTIFIED)});
mOnClickListener = new NotificationCardClickListener();
mAdapter = new EnhancedListAdapter(getActivity(),
R.layout.notification_list_item, cursor, columns, fields);
mAdapter.setViewBinder(new NotificationListViewBinder());
mListView.setAdapter(mAdapter);
mListView.setDismissCallback(new NotificationDismissCallback());
mListView.setOnItemClickListener(new NotificationClickListener());
mListView.setSwipingLayout(R.id.card);
mListView.enableSwipeToDismiss();
mListView.setSwipeDirection(EnhancedListView.SwipeDirection.BOTH);
}
private class NotificationListViewBinder implements SimpleCursorAdapter.ViewBinder{
@Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
TextView tv = null;
String value = "";
switch (view.getId()){
case R.id.user_icon_left :
value = cursor.getString(cursor.getColumnIndex("fname")) + " " +
cursor.getString(cursor.getColumnIndex("lname")) ;
ImageView iconView = (ImageView) view;
iconView.getDrawable().setColorFilter( getColor(value), Mode.MULTIPLY );
iconView.getDrawable().setLevel(5000);
return true;
case R.id.user_icon_right :
iconView = (ImageView) view;
if (!cursor.isNull(cursor.getColumnIndex("spouse_fname"))){
value = cursor.getString(cursor.getColumnIndex("spouse_fname")) + " " +
cursor.getString(cursor.getColumnIndex("spouse_lname")) ;
String spouse_value = cursor.getString(cursor.getColumnIndex("fname")) + " " +
cursor.getString(cursor.getColumnIndex("lname")) ;
iconView.getDrawable().setColorFilter( getColor(value, spouse_value), Mode.MULTIPLY );
} else {
value = cursor.getString(cursor.getColumnIndex("fname")) + " " +
cursor.getString(cursor.getColumnIndex("lname")) ;
iconView.getDrawable().setColorFilter( getColor(value), Mode.MULTIPLY );
}
iconView.getDrawable().setLevel(5000);
return true;
case R.id.initials :
tv = (TextView) view;
try {
value += cursor.getString(cursor.getColumnIndex("fname")).substring(0,1);
} catch (Exception e){}
if (!cursor.isNull(cursor.getColumnIndex("spouse_fname"))){
try {
value += cursor.getString(cursor.getColumnIndex("spouse_fname")).substring(0,1);
} catch (Exception e){}
} else {
try {
value += cursor.getString(cursor.getColumnIndex("lname")).substring(0,1);
} catch (Exception e){}
}
tv.setText(value);
return true;
case R.id.name :
tv = (TextView) view;
if (!cursor.isNull(cursor.getColumnIndex("spouse_fname"))){
value = cursor.getString(cursor.getColumnIndex("fname")) +
"&" + cursor.getString(cursor.getColumnIndex("spouse_fname")) +
" " + cursor.getString(cursor.getColumnIndex("lname")) ;
} else {
value = cursor.getString(cursor.getColumnIndex("fname")) + " " +
cursor.getString(cursor.getColumnIndex("lname")) ;
}
tv.setText(value);
return true;
case R.id.amount:
tv = (TextView) view;
if (cursor.getInt(cursor.getColumnIndex("type")) == Notification.SPECIAL_GIFT){
// on special gifts, put the value of the special gift rather than the
// partner's regular giving amount
try {
String message = cursor.getString(cursor.getColumnIndex("message"));
value = "$" + message.substring(0, message.length() - 2);
tv.setText(value);
return true;
} catch (Exception e){}
}
int amount = cursor.getInt(columnIndex)/100;
value = Integer.toString(amount);
switch (cursor.getInt(cursor.getColumnIndex("type"))){
case Notification.SPECIAL_GIFT:
break;
case Notification.CHANGE_PARTNER_TYPE:
case Notification.CHANGE_AMOUNT:
case Notification.CHANGE_STATUS:
switch (cursor.getInt(cursor.getColumnIndex("partner_type"))){
case ContactStatus.PARTNER_MONTHLY:
value += getString(R.string.per_month);
break;
case ContactStatus.PARTNER_ANNUAL:
value += getString(R.string.per_year);
break;
case ContactStatus.PARTNER_REGULAR:
value += getString(R.string.per_n_months);
int frequency = cursor.getInt(cursor.getColumnIndex("gift_frequency"));
value = value.replace("?", Integer.toString(frequency));
}
}
tv.setText("$" + value);
return true;
case R.id.type:
tv = (TextView) view;
switch (cursor.getInt(columnIndex)){
case Notification.CHANGE_PARTNER_TYPE:
int partnership = cursor.getInt(cursor.getColumnIndex("partner_type"));
if (partnership == ContactStatus.PARTNER_MONTHLY ||
partnership == ContactStatus.PARTNER_REGULAR){
int status = cursor.getInt(cursor.getColumnIndex("contact_status"));
if (status == ContactStatus.STATUS_NEW){
value = getString(R.string.new_partner);
} else if (status == ContactStatus.STATUS_CURRENT){
value = getString(R.string.restarted_partner);
}
} else {
value = getString(R.string.change_type);
}
break;
case Notification.CHANGE_STATUS:
switch (cursor.getInt(cursor.getColumnIndex("contact_status"))){
case ContactStatus.STATUS_LATE:
value = getString(R.string.late_partner);
break;
case ContactStatus.STATUS_LAPSED:
value = getString(R.string.lapsed_partner);
break;
case ContactStatus.STATUS_DROPPED:
value = getString(R.string.dropped);
break;
case ContactStatus.STATUS_NEW:
value = getString(R.string.new_partner);
break;
case ContactStatus.STATUS_CURRENT:
try {
int oldstatus = Integer.parseInt(cursor.getString(
cursor.getColumnIndex("message")));
if (oldstatus == ContactStatus.STATUS_LATE ||
oldstatus == ContactStatus.STATUS_LAPSED ||
oldstatus == ContactStatus.STATUS_DROPPED){
value = getString(R.string.restarted_partner);
} else if (cursor.getString(cursor.getColumnIndex("manual_set_expires"))
.compareTo( cursor.getString(cursor.getColumnIndex("date"))) >= 0){
value = getString(R.string.partner_continued);
} else if (oldstatus == ContactStatus.STATUS_NEW){
value = "Maintained";
}
} catch (Exception e){
}
break;
}
break;
case Notification.CHANGE_AMOUNT:
value = getString(R.string.amount_change);
break;
case Notification.SPECIAL_GIFT:
value = getString(R.string.special_gift);
break;
}
if (value != ""){
tv.setText(value);
return true;
} else {
return false;
}
case R.id.quickactions:
view.findViewById(R.id.action_icon).setOnClickListener(mOnClickListener);
view.findViewById(R.id.action_icon).setTag(cursor.getInt(1)); // contact ID
if (cursor.getInt(columnIndex) == Notification.SPECIAL_GIFT){
TextView phone = (TextView) view.findViewById(R.id.action_icon);
phone.setTextSize(TypedValue.COMPLEX_UNIT_PX,
getResources().getDimension(R.dimen.icon_text_size_small));
view.findViewById(R.id.overflow).setVisibility(View.VISIBLE);
view.findViewById(R.id.overflow).setOnClickListener(mOnClickListener);
view.findViewById(R.id.overflow).setTag(cursor.getInt(0));
return true;
} else {
TextView phone = (TextView) view.findViewById(R.id.action_icon);
phone.setTextSize(TypedValue.COMPLEX_UNIT_PX,
getResources().getDimension(R.dimen.icon_text_size));
view.findViewById(R.id.overflow).setVisibility(View.GONE);
return true;
}
case R.id.status:
tv = (TextView) view;
return false;
case R.id.date:
String date = cursor.getString(columnIndex);
if (cursor.getPosition() ==0){
view.setVisibility(View.VISIBLE);
((TextView) view).setText(TextTools.prettyDate(date));
} else {
cursor.moveToPrevious();
if (!date.equals(cursor.getString(columnIndex))){
view.setVisibility(View.VISIBLE);
((TextView) view).setText(TextTools.prettyDate(date));
} else {
view.setVisibility(View.GONE);
}
cursor.moveToNext();
}
return true;
}
return false;
}
private String getString(int id){
return getActivity().getResources().getString(id);
}
/* Simple hash & modulo to select a color from our list based on a
* string (so we can have a consistent color for a contact)
*/
}
/*
* Color for a given string (name), ensuring it is not thhe same color
* provided by value2
*/
static int getColor(String value, String value2){
int spouse_color = getColorIndex(value2, -1);
return icon_colors[(spouse_color + (icon_colors.length/2)) % icon_colors.length];
}
static int getColor(String value){
return icon_colors[getColorIndex(value, -1)];
}
static int getColorIndex(String value, int unwantedIndex){
int total = 0;
for (int i = 0; i < value.length(); i++){
total += (int) value.charAt(i);
}
total = total % icon_colors.length;
if (total == unwantedIndex){
total = (total +1) % icon_colors.length;
}
return total;
}
private class NotificationDismissCallback implements EnhancedListView.OnDismissCallback{
@Override
public EnhancedListView.Undoable onDismiss(EnhancedListView listView, final int position) {
final int archived_id = mAdapter.remove(position);
return new EnhancedListView.Undoable(){
@Override
public void undo() {
mAdapter.insert(archived_id);
}
};
}
}
private class EnhancedListAdapter extends SimpleCursorAdapter{
public EnhancedListAdapter(Context context, int layout, Cursor c, String[] from, int[] to){
super(context, layout, c, from, to);
}
public int remove(int position){
getCursor().moveToPosition(position);
int notificationId = getCursor().getInt(0);
MPDDBHelper.get().getWritableDatabase().execSQL(
"update notification set status = ? where _id = ?",
new String [] {Integer.toString(Notification.STATUS_ACKNOWLEDGED), Integer.toString(notificationId)});
Cursor cursor = MPDDBHelper.get().getReadableDatabase()
.rawQuery(NOTIFICATIONS_QUERY,
new String [] { Integer.toString(Notification.STATUS_NOTIFIED)});
swapCursor(cursor);
return notificationId;
}
public void insert(int archived_id){
MPDDBHelper.get().getWritableDatabase().execSQL(
"update notification set status = ? where _id = ?",
new String [] {Integer.toString(Notification.STATUS_NOTIFIED), Integer.toString(archived_id)});
Cursor cursor = MPDDBHelper.get().getReadableDatabase()
.rawQuery(NOTIFICATIONS_QUERY,
new String [] { Integer.toString(Notification.STATUS_NOTIFIED)});
swapCursor(cursor);
}
}
private class NotificationClickListener implements ListView.OnItemClickListener{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
Intent intent = new Intent(getActivity(), ContactDetailActivity.class);
mAdapter.getCursor().moveToPosition(position);
int contact_id = mAdapter.getCursor().getInt(
mAdapter.getCursor().getColumnIndex("contact_id"));
intent.putExtra("contactId", contact_id);
startActivity(intent);
}
}
private class NotificationCardClickListener implements View.OnClickListener, PopupMenu.OnMenuItemClickListener{
private View mView = null;
private Notification mNotification = null;
private ContactStatus mContactStatus = null;
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.overflow:
mView = v;
Integer nID = (Integer) v.getTag();
Log.i("net.bradmont.openmpd", "Loading notification " +nID);
mNotification = new Notification(nID);
mContactStatus = (ContactStatus) MPDDBHelper.getReferenceModel("contact_status")
.getByField("contact_id", mNotification.getInt("contact"));
PopupMenu popup = new PopupMenu(getActivity(), v);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.special_gift_card_actions, popup.getMenu());
popup.setOnMenuItemClickListener(this);
popup.show();
break;
case R.id.action_icon:
PhoneNumber phone = (PhoneNumber) MPDDBHelper
.getModelByField("phone_number", "contact_id", (Integer)v.getTag());
Log.i("net.bradmont.openmpd", "Calling contact " + v.getTag());
String number = phone.getString("number");
if (number.length() < 3){
((BaseActivity) getActivity()).userMessage(R.string.no_phone_number);
} else {
number = "tel:" + number;
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse(number));
getActivity().startActivity(intent);
}
}
}
public boolean onMenuItemClick(MenuItem item){
switch (item.getItemId()) {
case R.id.menu_make_monthly:
((BaseActivity) getActivity()).userMessage(R.string.assigned_monthly);
// do stuff to the ContactStatus
mContactStatus.setValue("partner_type", ContactStatus.PARTNER_MONTHLY);
mContactStatus.setValue("status", ContactStatus.STATUS_CURRENT);
mContactStatus.setValue("giving_amount", Integer.parseInt(mNotification.getString("message")));
mContactStatus.setValue("gift_frequency", 1);
// set up expiry date for manual status
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MONTH, 3); // expire in 3 months
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String expires_date = dateFormat.format(cal.getTime());
mContactStatus.setValue("manual_set_expires", expires_date);
mContactStatus.dirtySave();
AnalyticsFragment.clearCache();
return true;
case R.id.menu_make_quarterly:
((BaseActivity) getActivity()).userMessage(R.string.assigned_quarterly);
// do stuff to the ContactStatus
mContactStatus.setValue("partner_type", ContactStatus.PARTNER_REGULAR);
mContactStatus.setValue("status", ContactStatus.STATUS_CURRENT);
mContactStatus.setValue("giving_amount", Integer.parseInt(mNotification.getString("message")));
mContactStatus.setValue("gift_frequency", 6);
// set up expiry date for manual status
cal = Calendar.getInstance();
cal.add(Calendar.MONTH, 6); // expire in 14 months
dateFormat = new SimpleDateFormat("yyyy-MM-dd");
expires_date = dateFormat.format(cal.getTime());
mContactStatus.setValue("manual_set_expires", expires_date);
mContactStatus.dirtySave();
AnalyticsFragment.clearCache();
return true;
case R.id.menu_make_annual:
((BaseActivity) getActivity()).userMessage(R.string.assigned_annual);
// do stuff to the ContactStatus
mContactStatus.setValue("partner_type", ContactStatus.PARTNER_ANNUAL);
mContactStatus.setValue("status", ContactStatus.STATUS_CURRENT);
mContactStatus.setValue("giving_amount", Integer.parseInt(mNotification.getString("message")));
mContactStatus.setValue("gift_frequency", 12);
// set up expiry date for manual status
cal = Calendar.getInstance();
cal.add(Calendar.MONTH, 14); // expire in 14 months
dateFormat = new SimpleDateFormat("yyyy-MM-dd");
expires_date = dateFormat.format(cal.getTime());
mContactStatus.setValue("manual_set_expires", expires_date);
mContactStatus.dirtySave();
AnalyticsFragment.clearCache();
return true;
}
return false;
}
}
}