1package com.xtremelabs.robolectric.shadows;
2
3import android.app.AlarmManager;
4import android.app.PendingIntent;
5import android.content.Intent;
6import com.xtremelabs.robolectric.internal.Implementation;
7import com.xtremelabs.robolectric.internal.Implements;
8
9import java.util.ArrayList;
10import java.util.List;
11
12import static com.xtremelabs.robolectric.Robolectric.shadowOf;
13
14/**
15 * Shadows the {@code android.app.AlarmManager} class.
16 */
17@SuppressWarnings({"UnusedDeclaration"})
18@Implements(AlarmManager.class)
19public class ShadowAlarmManager {
20
21    private List<ScheduledAlarm> scheduledAlarms = new ArrayList<ScheduledAlarm>();
22
23    @Implementation
24    public void set(int type, long triggerAtTime, PendingIntent operation) {
25	    internalSet(type, triggerAtTime, 0L, operation);
26    }
27
28	@Implementation
29	public void setRepeating (int type, long triggerAtTime, long interval, PendingIntent operation){
30		internalSet(type, triggerAtTime, interval, operation);
31	}
32
33	private void internalSet(int type, long triggerAtTime, long interval, PendingIntent operation) {
34		Intent intent = shadowOf(operation).getSavedIntent();
35		for (ScheduledAlarm scheduledAlarm : scheduledAlarms) {
36			Intent scheduledIntent = shadowOf(scheduledAlarm.operation).getSavedIntent();
37			if (scheduledIntent.filterEquals(intent)) {
38				scheduledAlarms.remove(scheduledAlarm);
39				break;
40			}
41		}
42		scheduledAlarms.add(new ScheduledAlarm(type, triggerAtTime, interval, operation));
43	}
44
45	/**
46     * Non-Android accessor consumes and returns the next scheduled alarm on the
47     * AlarmManager's stack.
48     *
49     * @return the next scheduled alarm, wrapped in a
50     *         {@link ShadowAlarmManager.ScheduledAlarm} object
51     */
52    public ScheduledAlarm getNextScheduledAlarm() {
53        if (scheduledAlarms.isEmpty()) {
54            return null;
55        } else {
56            return scheduledAlarms.remove(0);
57        }
58    }
59
60    /**
61     * Non-Android accessor returns the most recent scheduled alarm without
62     * consuming it.
63     *
64     * @return the most recently scheduled alarm, wrapped in a
65     *         {@link ShadowAlarmManager.ScheduledAlarm} object
66     */
67    public ScheduledAlarm peekNextScheduledAlarm() {
68        if (scheduledAlarms.isEmpty()) {
69            return null;
70        } else {
71            return scheduledAlarms.get(0);
72        }
73    }
74
75    public List<ScheduledAlarm> getScheduledAlarms() {
76        return scheduledAlarms;
77    }
78
79    @Implementation
80    public void cancel(PendingIntent pendingIntent) {
81        final Intent intentTypeToRemove = shadowOf(pendingIntent).getSavedIntent();
82        for (ScheduledAlarm scheduledAlarm : new ArrayList<ScheduledAlarm>(scheduledAlarms)) {
83            final Intent alarmIntent = shadowOf(scheduledAlarm.operation).getSavedIntent();
84            if (intentTypeToRemove.filterEquals(alarmIntent)) {
85                scheduledAlarms.remove(scheduledAlarm);
86            }
87        }
88    }
89
90    /**
91     * Container object to hold an PendingIntent, together with the alarm
92     * parameters used in a call to {@code AlarmManager}
93     */
94    public class ScheduledAlarm {
95        public int type;
96        public long triggerAtTime;
97        public long interval;
98        public PendingIntent operation;
99
100        public ScheduledAlarm(int type, long triggerAtTime, PendingIntent operation) {
101            this(type, triggerAtTime, 0, operation);
102        }
103
104        public ScheduledAlarm(int type, long triggerAtTime, long interval, PendingIntent operation) {
105            this.type = type;
106            this.triggerAtTime = triggerAtTime;
107            this.operation = operation;
108            this.interval = interval;
109        }
110    }
111}
112