package com.evancharlton.mileage.models;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import com.evancharlton.mileage.FillUpsProvider;
import com.evancharlton.mileage.R;
import com.evancharlton.mileage.alarms.IntervalReceiver;
import com.evancharlton.mileage.views.intervals.ServiceIntervalsView;
public class ServiceInterval extends Model {
public static final String VEHICLE_ID = "vehicle_id";
public static final String CREATE_DATE = "creation_date";
public static final String DURATION = "interval_duration";
public static final String CREATE_ODOMETER = "creation_odometer";
public static final String DISTANCE = "interval_distance";
public static final String DESCRIPTION = "description";
public static final String REPEATING = "is_repeating";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/intervals");
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.evancharlton.interval";
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.evancharlton.interval";
public static final String DEFAULT_SORT_ORDER = VEHICLE_ID + " ASC";
public static final List<String> PROJECTION = new ArrayList<String>();
static {
PROJECTION.add(_ID);
PROJECTION.add(VEHICLE_ID);
PROJECTION.add(CREATE_DATE);
PROJECTION.add(DURATION);
PROJECTION.add(CREATE_ODOMETER);
PROJECTION.add(DISTANCE);
PROJECTION.add(DESCRIPTION);
// PROJECTION.add(REPEATING);
}
protected Calendar m_createDate = Calendar.getInstance();
protected long m_duration = 0L;
protected double m_createOdometer = 0D;
protected double m_distance = 0D;
protected String m_description = "";
protected long m_vehicleId = 0L;
protected boolean m_isRepeating = false;
public ServiceInterval() {
super(FillUpsProvider.MAINTENANCE_TABLE_NAME);
}
public ServiceInterval(ContentValues initialValues) {
this();
}
public ServiceInterval(long id) {
this();
openDatabase();
Cursor c = m_db.query(FillUpsProvider.MAINTENANCE_TABLE_NAME, ServiceInterval.getProjection(), ServiceInterval._ID + " = ?", new String[] {
String.valueOf(id)
}, null, null, null);
if (c.getCount() == 1) {
c.moveToFirst();
load(c);
closeDatabase(c);
} else {
throw new IllegalArgumentException("Invalid service interval ID (" + id + ") given!");
}
}
public ServiceInterval(Cursor c) {
this();
load(c);
}
protected void load(Cursor c) {
int index = c.getColumnIndex(_ID);
if (index >= 0) {
setId(c.getLong(index));
}
index = c.getColumnIndex(CREATE_DATE);
if (index >= 0) {
setCreateDate(c.getLong(index));
}
index = c.getColumnIndex(CREATE_ODOMETER);
if (index >= 0) {
setCreateOdometer(c.getDouble(index));
}
index = c.getColumnIndex(DISTANCE);
if (index >= 0) {
setDistance(c.getDouble(index));
}
index = c.getColumnIndex(DESCRIPTION);
if (index >= 0) {
setDescription(c.getString(index));
}
index = c.getColumnIndex(DURATION);
if (index >= 0) {
setDuration(c.getLong(index));
}
index = c.getColumnIndex(VEHICLE_ID);
if (index >= 0) {
setVehicleId(c.getLong(index));
}
index = c.getColumnIndex(REPEATING);
if (index >= 0) {
setRepeating(c.getInt(index) == 1);
}
}
public static List<ServiceInterval> getAll() {
return new ServiceInterval().loadAll();
}
public static String[] getProjection() {
return PROJECTION.toArray(new String[PROJECTION.size()]);
}
public List<ServiceInterval> loadAll() {
List<ServiceInterval> intervals = new ArrayList<ServiceInterval>();
openDatabase();
String[] projection = ServiceInterval.getProjection();
Cursor c = m_db.query(FillUpsProvider.MAINTENANCE_TABLE_NAME, projection, null, null, null, null, DEFAULT_SORT_ORDER);
c.moveToFirst();
while (!c.isAfterLast()) {
intervals.add(new ServiceInterval(c));
c.moveToNext();
}
closeDatabase(c);
return intervals;
}
@Override
public long save() {
openDatabase();
ContentValues values = new ContentValues();
values.put(ServiceInterval.CREATE_DATE, m_createDate.getTimeInMillis());
values.put(ServiceInterval.CREATE_ODOMETER, m_createOdometer);
values.put(ServiceInterval.DESCRIPTION, m_description);
values.put(ServiceInterval.DISTANCE, m_distance);
values.put(ServiceInterval.DURATION, m_duration);
values.put(ServiceInterval.VEHICLE_ID, m_vehicleId);
if (m_id == -1) {
// save a new record
m_id = m_db.insert(FillUpsProvider.MAINTENANCE_TABLE_NAME, null, values);
} else {
// update an existing record
m_db.update(FillUpsProvider.MAINTENANCE_TABLE_NAME, values, ServiceInterval._ID + " = ?", new String[] {
String.valueOf(m_id)
});
}
closeDatabase(null);
return m_id;
}
public void scheduleAlarm(Context context) {
if (m_id < 0) {
throw new IllegalStateException("The ServiceInterval must first be saved (or loaded)!");
}
Intent i = new Intent(context, IntervalReceiver.class);
i.putExtra(ServiceInterval._ID, m_id);
PendingIntent p = PendingIntent.getBroadcast(context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
long when = m_createDate.getTimeInMillis();
when += m_duration;
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (m_isRepeating) {
// TODO: this case isn't actually supported yet because it raises
// all kinds of interesting cases and complexities. For example: if
// a repeating alarm is set and then the ServiceInterval is deleted,
// what happens to the alarm? Also, does the date get updated every
// time a repeating alarm is triggered? If not, it could be awkward
// to the user. If so, how do we handle when the user gets an oil
// change (for example) early? Choices, choices...
am.setRepeating(AlarmManager.RTC_WAKEUP, when, m_duration, p);
} else {
am.set(AlarmManager.RTC_WAKEUP, when, p);
}
}
public void cancelAlarm(Context context) {
if (m_id < 0) {
throw new IllegalStateException("The ServiceInterval must first be saved (or loaded)!");
}
Intent i = new Intent(context, IntervalReceiver.class);
i.putExtra(ServiceInterval._ID, m_id);
PendingIntent p = PendingIntent.getBroadcast(context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.cancel(p);
}
@Override
public int validate() {
if (m_createDate.getTimeInMillis() == 0) {
return R.string.service_interval_error_create_date;
}
if (m_createOdometer < 0) {
return R.string.service_interval_error_create_odometer;
}
if (m_duration < 0) {
return R.string.service_interval_error_duration;
}
if (m_distance < 0) {
return R.string.service_interval_error_distance;
}
if (m_vehicleId < 0) {
return R.string.service_interval_error_vehicle_id;
}
if (m_description == null || m_description.length() == 0) {
return R.string.service_interval_error_description;
}
return 0;
}
public void raiseNotification(Context context) {
Intent i = new Intent(context, ServiceIntervalsView.class);
Vehicle v = new Vehicle(m_vehicleId);
String description = String.format("Due for %s", v.getTitle());
Notification notification = new Notification(R.drawable.gasbuttonx, getDescription(), System.currentTimeMillis());
i.putExtra(ServiceInterval._ID, m_id);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, i, 0);
notification.flags = Notification.FLAG_SHOW_LIGHTS | Notification.FLAG_AUTO_CANCEL;
notification.ledARGB = 0xFFFCAF15;
notification.ledOffMS = 500;
notification.ledOnMS = 500;
notification.vibrate = new long[] {
250,
250,
250,
250
};
notification.defaults = Notification.DEFAULT_ALL;
notification.setLatestEventInfo(context, getDescription(), description, contentIntent);
NotificationManager notificationMgr = (NotificationManager) context.getSystemService(Activity.NOTIFICATION_SERVICE);
if (notificationMgr != null) {
notificationMgr.notify((int) m_id, notification);
}
}
/**
* @return the createDate
*/
public Calendar getCreateDate() {
return m_createDate;
}
/**
* @param createDate the createDate to set
*/
public void setCreateDate(Calendar createDate) {
m_createDate = createDate;
}
public void setCreateDate(long milliseconds) {
m_createDate.setTimeInMillis(milliseconds);
}
/**
* @return the duration
*/
public long getDuration() {
return m_duration;
}
/**
* @param duration the duration to set
*/
public void setDuration(long duration) {
m_duration = duration;
}
/**
* @return the createOdometer
*/
public double getCreateOdometer() {
return m_createOdometer;
}
/**
* @param createOdometer the createOdometer to set
*/
public void setCreateOdometer(double createOdometer) {
m_createOdometer = createOdometer;
}
/**
* @return the distance
*/
public double getDistance() {
return m_distance;
}
/**
* @param distance the distance to set
*/
public void setDistance(double distance) {
m_distance = distance;
}
/**
* @return the description
*/
public String getDescription() {
return m_description;
}
/**
* @param description the description to set
*/
public void setDescription(String description) {
m_description = description;
}
/**
* @return the vehicleId
*/
public long getVehicleId() {
return m_vehicleId;
}
/**
* @param vehicleId the vehicleId to set
*/
public void setVehicleId(long vehicleId) {
m_vehicleId = vehicleId;
}
/**
* @return the isRepeating
*/
public boolean isRepeating() {
return m_isRepeating;
}
/**
* @param isRepeating the isRepeating to set
*/
public void setRepeating(boolean isRepeating) {
m_isRepeating = isRepeating;
}
public void setRepeating(int isRepeating) {
setRepeating(isRepeating == 1);
}
}