package net.bradmont.openmpd.controllers;
import android.os.Bundle;
import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.preference.PreferenceManager;
import net.bradmont.openmpd.helpers.Log;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import net.bradmont.openmpd.*;
import net.bradmont.openmpd.activities.ImportActivity;
import net.bradmont.openmpd.models.*;
import net.bradmont.openmpd.fragments.AnalyticsFragment;
import net.bradmont.openmpd.controllers.TntImporter;
import net.bradmont.openmpd.controllers.ContactsEvaluator;
import net.bradmont.supergreen.models.*;
public class TntImportService extends IntentService {
static final String UPDATE_FREQUENCY = "3"; // import values every 3 days
public TntImportService(){
super("TntImportService");
}
@Override
protected void onHandleIntent(Intent intent){
Log.i("net.bradmont.openmpd", "Starting updater thread");
// check if we have a network connection
if (!isNetworkAvailable()){
return;
}
Bundle b = intent.getExtras();
ArrayList<Integer> newdata = new ArrayList<Integer>();
ArrayList<Boolean> initialImport = new ArrayList<Boolean>();
if (MPDDBHelper.rawGet() == null){
MPDDBHelper dbh = new MPDDBHelper(this);
} else if (MPDDBHelper.get().getContext() != this){
MPDDBHelper.get().close();
MPDDBHelper dbh = new MPDDBHelper(this);
}
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("Importing Contacts")
.setContentText(" ");
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//notificationManager.notify(0, builder.build());
// import our stuff
startForeground(ContactsEvaluator.NOTIFICATION_ID, builder.build());
if (b.containsKey("net.bradmont.openmpd.account_id")){
ServiceAccount account = new ServiceAccount(b.getInt("net.bradmont.openmpd.account_id"));
if (isOld(account) || b.containsKey("net.bradmont.openmpd.force_update")){
if (account.getString("last_import") == null) {
initialImport.add(new Boolean(true));
} else {
initialImport.add(new Boolean(false));
}
TntImporter importer = new TntImporter(this, account, builder);
try {
if (importer.run() == true){
newdata.add(new Integer(account.getID()));
} else {
return;
}
} catch (Exception e){
LogItem.logError("TntImporter crashed", "", e);
notifyError(notificationManager, "TntImporter Exception", e);
}
}
} else if (b.containsKey("net.bradmont.openmpd.account_ids")){
int [] ids = b.getIntArray("net.bradmont.openmpd.account_ids");
for (int i = 0; i < ids.length; i++){
ServiceAccount account = new ServiceAccount(ids[i]);
if (isOld(account) || b.containsKey("net.bradmont.openmpd.force_update")){
if (account.getString("last_import") == null) {
initialImport.add(new Boolean(true));
} else {
initialImport.add(new Boolean(false));
}
TntImporter importer = new TntImporter(this, account, builder);
try {
if (importer.run() == true){
newdata.add(new Integer(account.getID()));
} else {
return;
}
} catch (Exception e){
LogItem.logError("TntImporter crashed", "", e);
notifyError(notificationManager, "TntImporter Exception", e);
}
}
}
}
// Evaluate contacts if we have newly imported data
if (newdata.size() > 0){
ContactsEvaluator evaluator = new ContactsEvaluator(this, builder, newdata, initialImport);
builder.setContentTitle("Evaluating Contacts")
.setContentText(" ");
ImportActivity.setStatus(-1, R.string.evaluating_contacts);
evaluator.run();
getSharedPreferences("openmpd", Context.MODE_PRIVATE)
.edit()
.putInt("onboardState", OpenMPD.ONBOARD_FINISHED)
.apply(); // Onboarding done
// clear the cache on our summary graph
AnalyticsFragment.clearCache();
AnalyticsFragment.createCache();
notifyUser(builder, notificationManager);
}
MPDDBHelper.get().close();
ImportActivity.onFinish();
stopForeground(true);
}
protected void notifyError(NotificationManager notificationManager, String message, Exception e){
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("OpenMPD import error")
.setContentText("Please click to report error.")
.setAutoCancel(true);
Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
emailIntent.setType("text/plain");
emailIntent.setData(Uri.parse("mailto: brad.stewart@p2c.com" ));
emailIntent.putExtra(Intent.EXTRA_EMAIL, "brad.stewart@p2c.com");
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "OpenMPD crash report: " + message);
String stackTrace = e.toString();
for (int i = 0; i < e.getStackTrace().length; i++){
stackTrace = stackTrace + "\n" + e.getStackTrace()[i].toString();
}
stackTrace = "OpenMPD import process ended with the following error:\n"
+ stackTrace;
emailIntent.putExtra(Intent.EXTRA_TEXT, stackTrace);
PendingIntent emailPendingIntent =
PendingIntent.getActivity(this, 0, Intent.createChooser(emailIntent, "Send email with..."), PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(emailPendingIntent);
notificationManager.notify(ContactsEvaluator.NOTIFICATION_ID +8, builder.build());
}
protected void notifyUser(NotificationCompat.Builder builder, NotificationManager notificationManager){
// notify of important changes
ModelList notifications = MPDDBHelper.filter("notification", "status", Notification.STATUS_NEW);
int new_partners, late_partners, lapsed_partners, restarted_partners, amount_changes, special_gifts;
new_partners = late_partners = lapsed_partners = restarted_partners = amount_changes = special_gifts = 0;
for (int i = 0; i < notifications.size(); i++){
Notification n = (Notification) notifications.get(i);
Contact contact = (Contact) n.getRelated("contact");
ContactStatus status = (ContactStatus)MPDDBHelper
.getReferenceModel("contact_status")
.getByField("contact_id", contact.getInt("id"));
switch (n.getInt("type")){
case Notification.CHANGE_PARTNER_TYPE:
int partnership = status.partnership(status.getInt("partner_type"));
if (partnership == R.string.per_month || partnership == R.string.per_n_months){
new_partners++;
}
break;
case Notification.CHANGE_STATUS:
switch(status.getInt("status")){
case ContactStatus.STATUS_LATE:
late_partners++;
break;
case ContactStatus.STATUS_LAPSED:
lapsed_partners++;
break;
case ContactStatus.STATUS_CURRENT:
try{
int temp = Integer.parseInt(status.getString("message"));
if (temp == ContactStatus.STATUS_LATE || temp == ContactStatus.STATUS_LAPSED){
restarted_partners++;
}
} catch (Exception e){ }
break;
}
break;
case Notification.CHANGE_AMOUNT:
amount_changes++;
break;
case Notification.SPECIAL_GIFT:
special_gifts++;
}
n.setValue("status", Notification.STATUS_NOTIFIED);
n.dirtySave();
}
int total = new_partners + late_partners + lapsed_partners + restarted_partners + amount_changes + special_gifts;
if (total > 0){
builder.setContentTitle(String.format("%d MPD notifications", total));
String content = "";
if (new_partners > 0){
content += String.format("%d new partner(s). ", new_partners);
}
if ( restarted_partners > 0){
content += String.format("%d restarted partner(s). ", restarted_partners);
}
if ( special_gifts > 0) {
content += String.format("%d special gift(s). ", special_gifts);
}
if ( late_partners > 0){
content += String.format("%d late partner(s). ", late_partners);
}
if ( lapsed_partners > 0){
content += String.format("%d lapsed partner(s). ", lapsed_partners);
}
if ( amount_changes > 0){
content += String.format("%d amount change(s). ", amount_changes);
}
builder.setContentText(content);
builder.setProgress(0, 0, false); // remove progress bar
Intent homeIntent = new Intent(this, HomeActivity.class);
homeIntent.putExtra("net.bradmont.openmpd.notifications", true);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(HomeActivity.class);
stackBuilder.addNextIntent(homeIntent);
PendingIntent homePendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(homePendingIntent);
notificationManager.notify(ContactsEvaluator.NOTIFICATION_ID +1, builder.build());
}
}
protected boolean isNetworkAvailable(){
ConnectivityManager connectivityManager
= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
private boolean isOld(ServiceAccount account){
String date = account.getString("last_import");
if (date == null){return true;}
Calendar now = Calendar.getInstance();
Calendar next_update = new GregorianCalendar();
String [] parts = date.split("-");
next_update.set(
Integer.parseInt(parts[0]),
Integer.parseInt(parts[1]) - 1,
Integer.parseInt(parts[2])
);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OpenMPD.get());
// check if set for office hours only
if (prefs.getBoolean("pref_notify_office_hours", false)){
// is it beween 9 and 5 on a weekday?
if ((now.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY || now.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) ||
(now.get(Calendar.HOUR_OF_DAY) < 9 || now.get(Calendar.HOUR_OF_DAY) > 17)){
Log.i("net.bradmont.openmpd", "Configured to import only during business hours, aborting.");
return false;
} else {
Log.i("net.bradmont.openmpd", "Currently business hours, continuing");
}
}
int update_frequency = Integer.parseInt(prefs.getString("pref_update_frequency", UPDATE_FREQUENCY));
next_update.add(Calendar.DAY_OF_MONTH, update_frequency);
// if next_update is before current time, we need to update, so return true:
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String nx = dateFormat.format(next_update.getTime());
String nw = dateFormat.format(now.getTime());
// it is utterly ridiculous that this should be easier than using the Calendar object...
if (nx.compareTo(nw) > 0){
Log.i("net.bradmont.openmpd", "Not updating; " + nx + " is after today, " + nw);
return false;
} else {
Log.i("net.bradmont.openmpd", "Updating; " + nx + " is before or equal to today, " + nw + ". Last was " + date);
return true;
}
}
}