package com.odoo.addons.mail;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import odoo.controls.OField;
import odoo.controls.fab.FloatingActionButton;
import odoo.controls.undobar.UndoBar;
import odoo.controls.undobar.UndoBar.UndoBarListener;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Toast;
import com.odoo.OSwipeListener.SwipeCallbacks;
import com.odoo.OTouchListener;
import com.odoo.R;
import com.odoo.addons.mail.models.MailMessage;
import com.odoo.addons.mail.providers.mail.MailProvider;
import com.odoo.base.res.ResPartner;
import com.odoo.orm.OColumn;
import com.odoo.orm.ODataRow;
import com.odoo.orm.sql.OQuery;
import com.odoo.support.AppScope;
import com.odoo.support.fragment.AsyncTaskListener;
import com.odoo.support.fragment.BaseFragment;
import com.odoo.support.fragment.OnSearchViewChangeListener;
import com.odoo.support.fragment.SyncStatusObserverListener;
import com.odoo.support.listview.OCursorListAdapter;
import com.odoo.support.listview.OCursorListAdapter.BeforeBindUpdateData;
import com.odoo.support.listview.OCursorListAdapter.OnRowViewClickListener;
import com.odoo.support.listview.OCursorListAdapter.OnViewBindListener;
import com.odoo.util.OControls;
import com.odoo.util.drawer.DrawerItem;
public class Mail extends BaseFragment implements OnRefreshListener,
LoaderManager.LoaderCallbacks<Cursor>, SyncStatusObserverListener,
OnItemClickListener, OnSearchViewChangeListener, OnViewBindListener,
OnClickListener, OnRowViewClickListener, SwipeCallbacks,
UndoBarListener, BeforeBindUpdateData {
public static final String TAG = Mail.class.getSimpleName();
public static final String KEY = "fragment_mail";
public static final String KEY_MESSAGE_ID = "mail_id";
public static final Integer REQUEST_COMPOSE_MAIL = 234;
private View mView = null;
private MailMessage db = null;
private ListView mailList = null;
private OCursorListAdapter mAdapter;
private String mCurFilter = null;
private Type mType = Type.Inbox;
private String selection = null;
private String[] args;
private OTouchListener mTouch;
private FloatingActionButton mFab;
private int lastSwipedMail = -1;
public enum Type {
Inbox, ToMe, ToDo, Archives, Outbox, Group
}
private int[] background_resources = new int[] {
R.drawable.message_listview_bg_toread_selector,
R.drawable.message_listview_bg_tonotread_selector };
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
setHasOptionsMenu(true);
setHasSyncStatusObserver(TAG, this, db());
scope = new AppScope(this);
initType();
return inflater.inflate(R.layout.mail, container, false);
}
private void initType() {
Bundle bundle = getArguments();
if (bundle.containsKey(KEY)) {
mType = Type.valueOf(bundle.getString(KEY));
createSelection();
}
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mView = view;
init(mView);
}
private void init(View view) {
mTouch = scope.main().getTouchAttacher();
setHasSwipeRefreshView(view, R.id.swipe_container, this);
mFab = (FloatingActionButton) view.findViewById(R.id.fabbutton);
mailList = (ListView) view.findViewById(R.id.mail_list_view);
mAdapter = new OCursorListAdapter(getActivity(), null,
R.layout.mail_list_item);
mAdapter.setOnViewBindListener(this);
mAdapter.setBeforeBindUpdateData(this);
mailList.setAdapter(mAdapter);
mailList.setOnItemClickListener(this);
mailList.setEmptyView(mView.findViewById(R.id.loadingProgress));
if (getPref().getBoolean("archive_with_swipe", false)) {
if (mType != Type.Archives)
mTouch.setSwipeableView(mailList, this);
}
mFab.listenTo(mailList);
mFab.setOnClickListener(this);
mAdapter.setOnRowViewClickListener(R.id.img_starred_mlist, this);
OControls.setVisible(view, R.id.loadingProgress);
OControls.setGone(view, R.id.emptyView);
getLoaderManager().initLoader(0, null, this);
}
@Override
public Object databaseHelper(Context context) {
return new MailMessage(context);
}
@Override
public List<DrawerItem> drawerMenus(Context context) {
Resources res = context.getResources();
List<DrawerItem> menu = new ArrayList<DrawerItem>();
menu.add(new DrawerItem(TAG, res.getString(R.string.drawer_inbox),
count_total(context, Type.Inbox), R.drawable.ic_action_inbox,
object(Type.Inbox)));
menu.add(new DrawerItem(TAG, res.getString(R.string.drawer_tome),
count_total(context, Type.ToMe), R.drawable.ic_action_user,
object(Type.ToMe)));
menu.add(new DrawerItem(TAG, res.getString(R.string.drawer_todo),
count_total(context, Type.ToDo),
R.drawable.ic_action_clipboard, object(Type.ToDo)));
menu.add(new DrawerItem(TAG, res.getString(R.string.drawer_archives),
0, R.drawable.ic_action_briefcase, object(Type.Archives)));
menu.add(new DrawerItem(TAG, res.getString(R.string.drawer_outbox),
count_total(context, Type.Outbox),
R.drawable.ic_action_unsent_mail, object(Type.Outbox)));
return menu;
}
private int count_total(Context context, Type key) {
if (db == null)
db = new MailMessage(context);
OQuery q = db.browse().columns("id");
q = setSelection(context, q, key);
return q.fetch().size();
}
private OQuery setSelection(Context context, OQuery query, Type type) {
switch (type) {
case Inbox:
query.addWhere("to_read", "=", 1);
query.addWhere("starred", "=", 0);
query.addWhere("id", "!=", 0);
break;
case ToMe:
query.addWhere("to_read", "=", 1);
query.addWhere("starred", "=", 0);
query.addWhere("res_id", "=", 0);
break;
case ToDo:
query.addWhere("to_read", "=", 1);
query.addWhere("starred", "=", 1);
break;
case Outbox:
query.addWhere("id", "=", 0);
break;
case Group:
Integer group_id = getArguments().getInt(Groups.KEY);
query.addWhere("res_id", "=", group_id);
query.addWhere("model", "=", "mail.group");
break;
case Archives:
query.addWhere("id", "!=", 0);
break;
default:
break;
}
return query;
}
public Fragment object(Type type) {
Mail mail = new Mail();
Bundle bundle = new Bundle();
bundle.putString(KEY, type.toString());
mail.setArguments(bundle);
return mail;
}
@Override
public void onRefresh() {
if (app().inNetwork()) {
scope.main().requestSync(MailProvider.AUTHORITY);
} else {
hideRefreshingProgress();
Toast.makeText(getActivity(), _s(R.string.no_connection),
Toast.LENGTH_LONG).show();
}
}
private void createSelection() {
selection = " ";
List<String> argsList = new ArrayList<String>();
switch (mType) {
case Inbox:
selection += " to_read = ? and starred = ? and id != ?";
argsList.add("1");
argsList.add("0");
argsList.add("0");
break;
case ToMe:
selection += " to_read = ? and starred = ? and res_id = ?";
argsList.add("1");
argsList.add("0");
argsList.add("0");
break;
case ToDo:
selection += " to_read = ? and starred = ?";
argsList.add("1");
argsList.add("1");
break;
case Outbox:
selection += " id = ?";
argsList.add("0");
break;
case Archives:
// Load all mails expect out box
selection += " id != ?";
argsList.add("0");
break;
case Group:
selection += " res_id = ? and model = ?";
argsList.add(getArguments().getInt(Groups.KEY) + "");
argsList.add("mail.group");
break;
}
args = argsList.toArray(new String[argsList.size()]);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle arg1) {
if (db().isEmptyTable()) {
scope.main().requestSync(MailProvider.AUTHORITY);
setSwipeRefreshing(true);
}
List<String> argsList = new ArrayList<String>();
createSelection();
if (mCurFilter != null) {
argsList.addAll(Arrays.asList(args));
selection += " and (author_name like ? or message_title like ?)";
argsList.add(mCurFilter + "%");
argsList.add("%" + mCurFilter + "%");
args = argsList.toArray(new String[argsList.size()]);
}
Uri uri = ((MailMessage) db()).mailUri();
return new CursorLoader(getActivity(), uri, new String[] {
"message_title", "author_name", "parent_id", "author_id",
"total_childs", "date", "to_read", "short_body", "starred" },
selection, args, "date DESC");
}
@Override
public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
mAdapter.changeCursor(cursor);
toggleEmptyView((cursor.getCount() == 0));
OControls.setGone(mView, R.id.loadingProgress);
}
@Override
public void onLoaderReset(Loader<Cursor> arg0) {
mAdapter.changeCursor(null);
}
@Override
public void onStatusChange(Boolean refreshing) {
if (!refreshing) {
hideRefreshingProgress();
} else
setSwipeRefreshing(true);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Cursor cr = (Cursor) mAdapter.getItem(position);
int _id = cr.getInt(cr.getColumnIndex(OColumn.ROW_ID));
int record_id = cr.getInt(cr.getColumnIndex("id"));
MailDetail mDetail = new MailDetail();
Bundle bundle = new Bundle();
bundle.putInt(OColumn.ROW_ID, _id);
bundle.putInt("id", record_id);
mDetail.setArguments(bundle);
startFragment(mDetail, true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.menu_mail, menu);
setHasSearchView(this, menu, R.id.menu_mail_search);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// case R.id.menu_mail_create:
// Intent i = new Intent(getActivity(), ComposeMail.class);
// startActivityForResult(i, REQUEST_COMPOSE_MAIL);
default:
break;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_COMPOSE_MAIL
&& resultCode == Activity.RESULT_OK) {
if (inNetwork()) {
scope.main().requestSync(MailProvider.AUTHORITY);
Toast.makeText(getActivity(), _s(R.string.message_sent),
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getActivity(), _s(R.string.message_cant_sent),
Toast.LENGTH_LONG).show();
}
}
}
@Override
public boolean onSearchViewTextChange(String newFilter) {
if (mCurFilter == null && newFilter == null)
return true;
if (mCurFilter != null && mCurFilter.equals(newFilter))
return true;
mCurFilter = newFilter;
getLoaderManager().restartLoader(0, null, this);
return true;
}
@Override
public void onSearchViewClose() {
// Do Nothing...
}
@Override
public void onViewBind(View view, Cursor cr, ODataRow row) {
// Setting background as per to_read
int to_read = cr.getInt(cr.getColumnIndex("to_read"));
view.setBackgroundResource(background_resources[to_read]);
// Setting starred color
ImageView imgStarred = (ImageView) view
.findViewById(R.id.img_starred_mlist);
int is_fav = 0;
is_fav = cr.getInt(cr.getColumnIndex("starred"));
imgStarred.setColorFilter((is_fav == 1) ? Color.parseColor("#FF8800")
: Color.parseColor("#aaaaaa"));
OField totalChilds = (OField) view.findViewById(R.id.totalChilds);
int replies = 0;
String total_childs = cr.getString(cr.getColumnIndex("total_childs"));
replies = Integer.parseInt(total_childs);
String childs = "";
if (replies > 0) {
childs = replies + " replies";
}
totalChilds.setText(childs);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.fabbutton) {
Intent i = new Intent(getActivity(), ComposeMail.class);
startActivityForResult(i, REQUEST_COMPOSE_MAIL);
}
if (v.getId() == R.id.checkForNewData) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
onRefresh();
}
}, 250);
}
}
public void toggleEmptyView(boolean show) {
OControls.toggleViewVisibility(mView, R.id.emptyView, show);
if (show)
setEmptyMessage();
}
private void setEmptyMessage() {
int icon = 0;
int str = R.string.label_no_records_found;
switch (mType) {
case Inbox:
icon = R.drawable.ic_action_inbox;
str = R.string.message_inbox_all_read;
break;
case ToMe:
icon = R.drawable.ic_action_user;
str = R.string.message_tome_all_read;
break;
case ToDo:
icon = R.drawable.ic_action_clipboard;
str = R.string.message_todo_all_read;
break;
case Outbox:
icon = R.drawable.ic_action_unsent_mail;
str = R.string.message_no_outbox_message;
break;
case Archives:
icon = R.drawable.ic_action_briefcase;
break;
case Group:
icon = R.drawable.ic_action_social_group;
str = R.string.message_no_group_message;
break;
}
OControls.setImage(mView, R.id.emptyListIcon, icon);
OControls.setText(mView, R.id.emptyListMessage, _s(str));
if (mType != Type.Outbox)
mView.findViewById(R.id.checkForNewData).setOnClickListener(this);
else
mView.findViewById(R.id.checkForNewData).setVisibility(View.GONE);
}
private void restartLoader() {
getLoaderManager().restartLoader(0, null, this);
}
@Override
public void onRowViewClick(int position, Cursor cursor, View view,
View parent) {
final Cursor c = cursor;
switch (view.getId()) {
case R.id.img_starred_mlist:
String starred = "";
starred = c.getString(c.getColumnIndex("starred"));
final boolean is_fav = !starred.equals("1");
if (inNetwork()) {
ImageView imgStarred = (ImageView) view;
imgStarred.setColorFilter((is_fav) ? Color
.parseColor("#FF8800") : Color.parseColor("#aaaaaa"));
// markAsTodo
scope.main().newBackgroundTask(new AsyncTaskListener() {
@Override
public Object onPerformTask() {
MailMessage mail = (MailMessage) db();
mail.markAsTodo(c, is_fav);
return null;
}
@Override
public void onFinish(Object result) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
restartLoader();
}
});
}
}).execute();
} else {
Toast.makeText(getActivity(), _s(R.string.no_connection),
Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
}
@Override
public boolean canSwipe(int position) {
return true;
}
@Override
public void onSwipe(View view, int[] positions) {
for (int pos : positions) {
Cursor cr = mAdapter.getCursor();
cr.moveToPosition(pos);
lastSwipedMail = cr.getInt(cr.getColumnIndex(OColumn.ROW_ID));
toggleMailToRead(lastSwipedMail, false);
showUndoBar();
}
}
private void showUndoBar() {
if (getPref().getBoolean("mail_show_undo_archive", true)) {
UndoBar undoBar = new UndoBar(getActivity());
undoBar.setMessage("Mail archived");
undoBar.setDuration(7000);
undoBar.setListener(this);
undoBar.show(true);
} else {
updateArchiveOnServer();
}
}
@Override
public void onHide() {
if (lastSwipedMail != -1) {
updateArchiveOnServer();
lastSwipedMail = -1;
}
}
private void updateArchiveOnServer() {
if (inNetwork()) {
MailMessage mail = (MailMessage) db();
mail.markMailReadUnread(lastSwipedMail, false);
}
}
@Override
public void onUndo(Parcelable token) {
toggleMailToRead(lastSwipedMail, true);
lastSwipedMail = -1;
}
private void toggleMailToRead(int mailId, boolean to_read) {
ContentValues values = new ContentValues();
values.put("to_read", (to_read) ? 1 : 0);
if (!inNetwork())
values.put("is_dirty", 1);
String selection = OColumn.ROW_ID + " = ? or parent_id = ?";
String[] args = new String[] { mailId + "", mailId + "" };
if (to_read) {
selection = OColumn.ROW_ID + " = ?";
args = new String[] { mailId + "" };
}
getActivity().getContentResolver().update(db().uri(), values,
selection, args);
}
@Override
public ODataRow updateDataRow(Cursor cr) {
String author_image = "false";
ODataRow row = new ODataRow();
if (!cr.getString(cr.getColumnIndex("author_id")).equals("false")) {
ODataRow partner = new ResPartner(getActivity()).select(cr
.getInt(cr.getColumnIndex("author_id")));
if (partner != null) {
author_image = partner.getString("image_small");
}
}
row.put("author_id_image_small", author_image);
return row;
}
}