package net.sabi.pester; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import danger.app.Application; import danger.internal.Date; import danger.util.LocaleUtils; import danger.util.StdActiveList; import danger.util.StdActiveObject; import danger.util.DEBUG; import danger.util.format.DateFormat; import danger.util.format.StringFormat; public class Alarm extends StdActiveObject { private static final int VERSION_1 = 1; // persisted private String mMessage; private int mType; private int mPeriod; // XXX rename to 'interval' private Date mDate; // transient private int mState; private danger.app.Alarm mAlarm; public Alarm() { mState = STATE_INVALID; mAlarm = new danger.app.Alarm(0, Application.getCurrentApp(), this); } public String getMessage() { return mMessage; } public int getPeriod() { return mPeriod; } public boolean getUsesPeriod() { return mType != TYPE_DATE; } public boolean getRepeating() { return mType == TYPE_PERIODIC_REPEATING; } public Date getDate() { return mDate; } public void setMessage(String message) { mMessage = message; } public void setPeriod(int period, boolean repeating) { mType = repeating ? TYPE_PERIODIC_REPEATING : TYPE_PERIODIC; mPeriod = period; } public void setDate(Date date) { mType = TYPE_DATE; mDate = date; } public byte[] toByteArray() { try { ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); DataOutputStream dataStream = new DataOutputStream(byteStream); dataStream.writeByte(VERSION_1); dataStream.writeUTF(mMessage); dataStream.writeInt(mPeriod); dataStream.writeInt(mDate.getUnixTimeGMT()); dataStream.writeInt(mType); dataStream.flush(); return byteStream.toByteArray(); } catch (Exception e) { // XXX do something } return null; } public void fromByteArray(byte[] data) { try { ByteArrayInputStream byteStream = new ByteArrayInputStream(data); DataInputStream dataStream = new DataInputStream(byteStream); byte version = dataStream.readByte(); if (version != VERSION_1) { // XXX barf } mMessage = dataStream.readUTF(); mPeriod = dataStream.readInt(); mType = dataStream.readInt(); } catch (Exception e) { // XXX do something } } void beginEditing() { mState = STATE_EDITING; mAlarm.deactivate(); } void resume() { mState = STATE_SCHEDULED; int period = mDate.getDangerTimeGMT() - new Date().getDangerTimeGMT(); if (period < 0) period = 0; mAlarm.resetWake(period); DEBUG.p("resetWake: " + description() + " - " + period + "s left"); update(); } void schedule() { if (getUsesPeriod()) { mDate = new Date(); mDate.addSeconds(mPeriod); } resume(); } void dismiss() { if (getRepeating()) schedule(); else ((StdActiveList)getDelegate()).removeItem(this); } void cancel() { mState = STATE_INVALID; mAlarm.deactivate(); } public String description() { StringBuffer sb = new StringBuffer(); switch (mState) { case STATE_INVALID: sb.append("invalid "); break; case STATE_EDITING: sb.append("editing "); break; case STATE_SCHEDULED: sb.append("scheduled "); break; } switch (mType) { case TYPE_PERIODIC: sb.append("periodic (").append(mPeriod).append("s) "); break; case TYPE_PERIODIC_REPEATING: sb.append("repeating periodic (").append(mPeriod).append("s) "); break; case TYPE_DATE: sb.append("date (").append(getDateTimeString()).append(") "); break; } sb.append("alarm: "); sb.append('"').append(mMessage).append('"'); return sb.toString(); } protected static String dateTimeString(Date date) { if (date == null) return null; String layout = LocaleUtils.getDateTimePattern(); String timeFormat = LocaleUtils.getMediumTimeFormat(); String dateFormat = LocaleUtils.getShortDateFormat(); return StringFormat.withFormat(layout, DateFormat.withFormat(timeFormat, date), DateFormat.withFormat(dateFormat, date)); } public String getDateTimeString() { return dateTimeString(mDate); } public String toString() { return mMessage; } public static final int TYPE_PERIODIC = 0; public static final int TYPE_PERIODIC_REPEATING = 1; public static final int TYPE_DATE = 2; public static final int STATE_INVALID = 0; public static final int STATE_EDITING = 1; public static final int STATE_SCHEDULED = 2; }