package com.odoo.addons.mail.services;
import java.util.ArrayList;
import java.util.List;
import odoo.OArguments;
import odoo.ODomain;
import odoo.Odoo;
import org.json.JSONArray;
import org.json.JSONObject;
import android.content.Context;
import android.content.Intent;
import android.content.SyncResult;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import com.odoo.App;
import com.odoo.MainActivity;
import com.odoo.R;
import com.odoo.addons.mail.models.MailMessage;
import com.odoo.base.ir.Attachments;
import com.odoo.base.res.ResPartner;
import com.odoo.base.res.ResUsers;
import com.odoo.orm.OColumn;
import com.odoo.orm.ODataRow;
import com.odoo.orm.OFieldsHelper;
import com.odoo.orm.OSyncHelper;
import com.odoo.orm.OValues;
import com.odoo.support.OUser;
import com.odoo.support.service.OSyncAdapter;
import com.odoo.support.service.OSyncFinishListener;
import com.odoo.support.service.OSyncService;
import com.odoo.util.JSONUtils;
import com.odoo.util.notification.NotificationBuilder;
public class MailSyncService extends OSyncService implements
OSyncFinishListener {
public static final String TAG = MailSyncService.class.getSimpleName();
@Override
public OSyncAdapter getSyncAdapter() {
return new OSyncAdapter(getApplicationContext(), new MailMessage(
getApplicationContext()), this, true);
}
@Override
public void performDataSync(OSyncAdapter adapter, Bundle extras, OUser user) {
Context mContext = getApplicationContext();
try {
MailMessage mdb = new MailMessage(mContext);
mdb.setUser(user);
if (sendMails(mContext, user, mdb, mdb.getSyncHelper())) {
updateMails(user);
}
ODomain domain = new ODomain();
if (extras.containsKey(MailGroupSyncService.KEY_GROUP_IDS)) {
JSONArray group_ids = new JSONArray(
extras.getString(MailGroupSyncService.KEY_GROUP_IDS));
domain.add("res_id", "in", group_ids);
domain.add("model", "=", "mail.group");
}
adapter.syncDataLimit(30).onSyncFinish(this).setDomain(domain);
} catch (Exception e) {
e.printStackTrace();
}
}
private Boolean sendMails(Context context, OUser user, MailMessage mails,
OSyncHelper helper) {
for (ODataRow mail : mails.select("id = ?", new Object[] { 0 })) {
try {
JSONArray partner_ids = new JSONArray();
JSONArray p_ids = new JSONArray();
List<ODataRow> partners = mail.getM2MRecord("partner_ids")
.browseEach();
p_ids = JSONUtils.toArray(getPartnersServerId(partners));
partner_ids.put(6);
partner_ids.put(false);
partner_ids.put(p_ids);
// Attachments
List<Integer> attachments = getAttachmentIds(mail);
Object attachment_ids = false;
if (attachments.size() > 0) {
JSONArray attachmentIds = new JSONArray();
attachmentIds.put(6);
attachmentIds.put(false);
attachmentIds.put(JSONUtils.toArray(attachments));
attachment_ids = new JSONArray().put(attachmentIds);
}
if ((Integer) mail.getM2ORecord("parent_id").getId() == 0) {
_sendMail(mail, partner_ids, attachment_ids, helper, mails);
} else {
JSONArray attachments_reply = new JSONArray();
if (!attachment_ids.toString().equals("false")) {
attachments_reply = new JSONArray(JSONUtils.toArray(
attachments).toString());
}
ODataRow parent = mail.getM2ORecord("parent_id").browse();
sendReply(context, parent, mail, partner_ids,
attachments_reply, helper, mails);
}
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "send Mails()" + e.getMessage());
}
}
return true;
}
private void _sendMail(ODataRow mail, JSONArray partner_ids,
Object attachment_ids, OSyncHelper helper, MailMessage mails) {
try {
JSONObject arguments = new JSONObject();
arguments.put("composition_mode", "comment");
arguments.put("model", false);
arguments.put("parent_id", false);
arguments.put("subject", mail.getString("subject"));
arguments.put("body", mail.getString("body"));
arguments.put("post", true);
arguments.put("notify", false);
arguments.put("same_thread", true);
arguments.put("use_active_domain", false);
arguments.put("reply_to", false);
arguments.put("res_id", false);
arguments.put("record_name", false);
arguments.put("partner_ids", new JSONArray().put(partner_ids));
arguments.put("template_id", false);
arguments.put("attachment_ids", attachment_ids);
JSONObject kwargs = new JSONObject();
kwargs.put("context", helper.getContext(new JSONObject()));
OArguments args = new OArguments();
args.add(arguments);
String model = "mail.compose.message";
// Creating compose message
Object message_id = helper.callMethod(model, "create", args, null,
kwargs);
// sending mail
args = new OArguments();
args.add(new JSONArray().put(message_id));
args.add(helper.getContext(null));
helper.callMethod(model, "send_mail", args, null, null);
mails.resolver().delete(mail.getInt(OColumn.ROW_ID));
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "_sendMail() : " + e.getMessage());
}
}
private void sendReply(Context context, ODataRow parent, ODataRow mail,
JSONArray partner_ids, Object attachment_ids, OSyncHelper helper,
MailMessage mails) {
try {
// sending reply
String model = (parent.getString("model").equals("false")) ? "mail.thread"
: parent.getString("model");
String method = "message_post";
Object res_model = (parent.getString("model").equals("false")) ? false
: parent.getString("model");
Object res_id = (parent.getInt("res_id") == 0) ? false : parent
.getInt("res_id");
JSONObject jContext = new JSONObject();
jContext.put("default_model", res_model);
jContext.put("default_res_id", res_id);
jContext.put("default_parent_id", parent.getInt("id"));
jContext.put("mail_post_autofollow", true);
jContext.put("mail_post_autofollow_partner_ids", new JSONArray());
JSONObject kwargs = new JSONObject();
kwargs.put("context", jContext);
kwargs.put("subject", mail.getString("subject"));
kwargs.put("body", mail.getString("body"));
kwargs.put("parent_id", parent.getInt("id"));
kwargs.put("attachment_ids", attachment_ids);
kwargs.put("partner_ids", new JSONArray().put(partner_ids));
OArguments args = new OArguments();
args.add(new JSONArray().put(res_id));
Integer messageId = (Integer) helper.callMethod(model, method,
args, null, kwargs);
OValues vals = new OValues();
vals.put(OColumn.ROW_ID, mail.getInt(OColumn.ROW_ID));
vals.put("id", messageId);
mails.resolver().update(vals.getInt(OColumn.ROW_ID), vals);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "send Reply()" + e.getMessage());
}
}
private List<Integer> getAttachmentIds(ODataRow row) {
List<Integer> ids = new ArrayList<Integer>();
try {
Attachments helper = new Attachments(getApplicationContext());
for (ODataRow attachment : row.getM2MRecord("attachment_ids")
.browseEach()) {
int id = helper.pushToServer(attachment);
if (id != 0) {
ids.add(id);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return ids;
}
private Boolean updateMails(OUser user) {
_updateUpStream(user);
_updateDownStream(user);
return true;
}
private void _updateUpStream(OUser user) {
Context context = getApplicationContext();
MailMessage mail = new MailMessage(context);
Cursor cr = context.getContentResolver().query(mail.uri(),
new String[] { "id", OColumn.ROW_ID, "to_read", "parent_id" },
"is_dirty = ? or is_dirty = ?", new String[] { "1", "true" },
null);
List<Integer> finished = new ArrayList<Integer>();
if (cr.moveToFirst()) {
do {
int parent_id = cr.getInt(cr.getColumnIndex("parent_id"));
int sync_id = parent_id;
if (parent_id == 0) {
sync_id = cr.getInt(cr.getColumnIndex(OColumn.ROW_ID));
}
if (finished.indexOf(sync_id) <= -1) {
Boolean to_read = (cr.getInt(cr.getColumnIndex("to_read")) == 1) ? true
: false;
mail.markMailReadUnread(sync_id, to_read);
finished.add(sync_id);
}
} while (cr.moveToNext());
}
cr.close();
}
private void _updateDownStream(OUser user) {
Context context = getApplicationContext();
App app = (App) context;
MailMessage mail = new MailMessage(context);
ResUsers users = new ResUsers(context);
try {
Odoo odoo = app.getOdoo();
ODomain domain = new ODomain();
domain.add("id", "in", new JSONArray(mail.ids().toString()));
JSONObject fields = new JSONObject();
fields.accumulate("fields", "to_read");
fields.accumulate("fields", "starred");
fields.accumulate("fields", "vote_user_ids");
JSONArray result = odoo.search_read(mail.getModelName(), fields,
domain.get()).getJSONArray("records");
for (int i = 0; i < result.length(); i++) {
JSONObject row = result.getJSONObject(i);
int id = row.getInt("id");
int to_read = (row.getBoolean("to_read")) ? 1 : 0;
int starred = (row.getBoolean("starred")) ? 1 : 0;
List<Integer> vote_user_ids = JSONUtils.toList(row
.getJSONArray("vote_user_ids"));
int row_id = mail.selectRowId(id);
OValues values = new OValues();
values.put("to_read", to_read);
values.put("starred", starred);
List<Integer> local_vote_user_ids = new ArrayList<Integer>();
for (Integer user_id : vote_user_ids) {
OValues vals = new OValues();
vals.put("id", user_id);
local_vote_user_ids.add(users.createORReplace(vals));
}
values.put("vote_user_ids", local_vote_user_ids.toString());
mail.resolver().update(row_id, values);
}
OFieldsHelper userFields = new OFieldsHelper(new String[] {
"login", "name" });
JSONArray user_result = odoo.search_read(users.getModelName(),
userFields.get(), null).getJSONArray("records");
List<Integer> local_uids = new ArrayList<Integer>();
for (ODataRow rows : users.select()) {
local_uids.add(rows.getInt("id"));
}
for (int i = 0; i < user_result.length(); i++) {
JSONObject row = user_result.getJSONObject(i);
if (!local_uids.contains(row.getInt("id"))) {
OValues values = new OValues();
values.put("id", row.getInt("id"));
values.put("name", row.getString("name"));
values.put("login", row.getString("login"));
values.put("is_dirty", false);
users.createORReplace(values);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public OSyncAdapter performSync(SyncResult syncResult) {
App app = (App) getApplicationContext();
int newTotal = (int) syncResult.stats.numInserts;
newTotal = (newTotal != 0) ? newTotal / 2 : newTotal;
if (!app.appOnTop() && newTotal > 0) {
NotificationBuilder notification = new NotificationBuilder(
getApplicationContext());
notification.setAutoCancel(true);
notification.setIcon(R.drawable.ic_odoo_o);
notification.setTitle(newTotal + " unread messages");
notification.setText(newTotal + " new message received (Odoo)");
Intent rIntent = new Intent(getApplicationContext(),
MainActivity.class);
notification.setResultIntent(rIntent);
notification.build().show();
}
return null;
}
public List<Integer> getPartnersServerId(List<ODataRow> rows) {
List<Integer> pIds = new ArrayList<Integer>();
for (ODataRow row : rows) {
int server_id = row.getInt("id");
if (server_id == 0) {
ODomain domain = new ODomain();
domain.add("email", "ilike", row.getString("email"));
server_id = getPartnerId(domain, row);
}
pIds.add(server_id);
}
return pIds;
}
public int getPartnerId(ODomain domain, ODataRow row) {
int server_id = 0;
try {
Context context = getApplicationContext();
ResPartner partner = new ResPartner(context);
App app = (App) context;
Odoo odoo = app.getOdoo();
JSONObject fields = new JSONObject();
fields.accumulate("fields", "email");
JSONObject result = odoo.search_read(partner.getModelName(),
fields, domain.get());
JSONArray records = result.getJSONArray("records");
if (records.length() > 0) {
JSONObject record = records.getJSONObject(0);
server_id = record.getInt("id");
OValues vals = new OValues();
vals.put("id", server_id);
partner.resolver().update(row.getInt(OColumn.ROW_ID), vals);
} else {
// Creating partner on server
server_id = partner.getSyncHelper().create(partner, row);
Log.v(TAG, "partner created on server " + server_id);
}
} catch (Exception e) {
e.printStackTrace();
}
return server_id;
}
}