Stay alive unless closed from menu
[WhereAmI.git] / src / org / average / whereami / PhoneLog.java
1 package org.average.whereami;
2
3 import org.average.whereami.APIBase;
4 import org.average.whereami.Oracle;
5 import org.average.whereami.Utterance;
6 import org.average.whereami.PersistentStore;
7 import org.average.whereami.SayWhen;
8
9 import java.io.IOException;
10 import java.net.UnknownHostException;
11 import org.apache.http.conn.HttpHostConnectException;
12
13 import com.google.api.client.googleapis.json.GoogleJsonResponseException;
14 import com.google.api.client.http.HttpResponseException;
15 import com.google.api.client.util.DateTime;
16 import com.google.api.services.calendar.Calendar;
17 import com.google.api.services.calendar.CalendarRequest;
18 import com.google.api.services.calendar.model.CalendarList;
19 import com.google.api.services.calendar.model.CalendarListEntry;
20 import com.google.api.services.calendar.model.Event;
21 import com.google.api.services.calendar.model.Events;
22 import com.google.common.collect.Lists;
23
24 import android.content.Context;
25 import android.content.res.Resources;
26 import android.text.format.Time;
27 import android.util.Log;
28
29 public final class PhoneLog extends Oracle {
30
31         final String TAG = getClass().getName();
32
33         private String calendar_name;
34         private String peer_name;
35         private String calendar_id;
36         private String nocalendar;
37         private String noevents;
38         private String last_call;
39         private String in_call;
40         private String out_call;
41         private String duration;
42         private String lessthan;
43         private String minutes1;
44         private String minutes2to4;
45         private String minutes5up;
46         private SayWhen sayWhen;
47         private Calendar calendar;
48
49         public PhoneLog(APIBase base) {
50                 super(base);
51                 nocalendar = base.res.getString(R.string.nocalendar);
52                 noevents = base.res.getString(R.string.noevents);
53                 last_call = base.res.getString(R.string.last_call);
54                 in_call = base.res.getString(R.string.in_call);
55                 out_call = base.res.getString(R.string.out_call);
56                 duration = base.res.getString(R.string.duration);
57                 lessthan = base.res.getString(R.string.lessthan);
58                 minutes1 = base.res.getString(R.string.minutes1);
59                 minutes2to4 = base.res.getString(R.string.minutes2to4);
60                 minutes5up = base.res.getString(R.string.minutes5up);
61                 sayWhen = new SayWhen(base.res);
62                 calendar_name = base.store.get("calendar_name");
63                 peer_name = base.store.get("peer_name");
64                 calendar_id = base.store.get("calendar_id");
65                 calendar = Calendar.builder(base.httpTransport,
66                                                         base.jsonFactory)
67                         .setHttpRequestInitializer(
68                                                 base.accessProtectedResource)
69                         .setApplicationName("WhereAmI/1.0").build();
70         }
71
72         @Override
73         public final Utterance getResult() {
74                 try {
75                         Log.v(TAG, "entering getResult");
76                         if (calendar_id == null || calendar_id == "") {
77                                 calendar_id = scanCalendars(calendar_name);
78                         }
79                         if (calendar_id == null || calendar_id == "") {
80                                 return new Utterance(true,
81                                         nocalendar + " \"" +
82                                         calendar_name + "\"");
83                         } else {
84                                 base.store.put("calendar_id", calendar_id);
85                                 return new Utterance(true,
86                                         scanEvents(calendar_id, peer_name));
87                         }
88                 } catch (GoogleJsonResponseException e) {
89                         Log.e(TAG, "GoogleJsonResponseException: " + e);
90                         if (e.getResponse().getStatusCode() == 401) {
91                                 return new Utterance(false,
92                                         base.authErrorMessage + "\n" +
93                                         e.getMessage());
94                         } else {
95                                 return new Utterance(false,
96                                         e.getMessage());
97                         }
98                 } catch (HttpResponseException e) {
99                         Log.e(TAG, "HttpResponseException: " + e);
100                         return new Utterance(false, e.getMessage());
101                 } catch (UnknownHostException e) {
102                         Log.e(TAG, "UnknownHostException: " + e);
103                         return new Utterance(false,
104                                         base.connectErrorMessage + "\n" +
105                                         e.getMessage());
106                 } catch (HttpHostConnectException e) {
107                         Log.e(TAG, "HttpHostConnectException: " + e);
108                         return new Utterance(false,
109                                         base.connectErrorMessage + "\n" +
110                                         e.getMessage());
111                 } catch (IOException e) {
112                         Log.e(TAG, "IOException: " + e);
113                         return new Utterance(false, e.getMessage());
114                 }
115         }
116
117         private String scanCalendars(String calendar_name)
118                                                 throws java.io.IOException {
119                 String res = "";
120                 Log.v(TAG, "Entering scanCalendars for \"" +
121                         calendar_name + "\"");
122
123                 CalendarList cl = calendar.calendarList().list().execute();
124                 while (true) {
125                         String pt = cl.getNextPageToken();
126                         Log.v(TAG, "got cl with pt=" + pt);
127                         for (CalendarListEntry le : cl.getItems()) {
128                                 Log.v(TAG, "entry " + le.getId() + ":\"" +
129                                         le.getSummary() + "\"");
130                                 if (le.getSummary().equals(calendar_name)) {
131                                         res = le.getId();
132                                         //break; // get all in the log
133                                 }
134                         }
135                         if (pt != null && pt != "") {
136                                 cl = calendar.calendarList().list()
137                                         .setPageToken(pt).execute();
138                         } else {
139                                 break;
140                         }
141                 }
142
143                 return res;
144         }
145
146         private String scanEvents(String calendar_id, String peer_name)
147                                                 throws java.io.IOException {
148                 Log.v(TAG, "Entering scanEvents for \"" +
149                         peer_name + "\" in \"" + calendar_id + "\"");
150                 Integer count = 0;
151                 Time ago = new Time();
152                 ago.set(System.currentTimeMillis() - 604800000L);
153                 Long latestStartTime = 0L;
154                 Long latestStopTime = 0L;
155                 Boolean latestWasOutgoing = false;
156                 Boolean wasFound = false;
157
158                 Events events = calendar.events().list(calendar_id)
159                         .setTimeMin(ago.format3339(false))
160                         .setQ(peer_name)
161                         .execute();
162                 while (true) {
163                         String pt = events.getNextPageToken();
164                         Log.v(TAG, "got events with pt=" + pt);
165                         for (Event event : events.getItems()) {
166                                 count++;
167                                 String evSummary = event.getSummary();
168                                 Long evStart = event.getStart()
169                                                 .getDateTime().getValue();
170                                 Long evStop = event.getEnd()
171                                                 .getDateTime().getValue();
172                                 Log.v(TAG, "event " + evStart +
173                                         " - " + evStop +
174                                         " : \"" + evSummary + "\"");
175                                 if ((evSummary.startsWith("Call To ") ||
176                                      evSummary.startsWith("Call From ")) &&
177                                     evStart > latestStartTime) {
178                                                 latestStartTime = evStart;
179                                                 latestStopTime = evStop;
180                                                 latestWasOutgoing = evSummary
181                                                         .startsWith("Call To ");
182                                                 wasFound = true;
183                                 }
184                         }
185                         if (count < 100 && pt != null && pt != "") {
186                                 events = calendar.events().list(calendar_id)
187                                         .setTimeMin(ago.format3339(false))
188                                         .setQ(peer_name)
189                                         .setPageToken(pt).execute();
190                         } else {
191                                 break;
192                         }
193                 }
194
195                 if (wasFound) {
196                         return makeMessage(latestStartTime, latestStopTime,
197                                                 latestWasOutgoing);
198                 } else {
199                         return noevents;
200                 }
201         }
202
203         private String makeMessage(Long latestStartTime, Long latestStopTime,
204                                         Boolean latestWasOutgoing) {
205                 Time stime = new Time();
206                 stime.set(latestStartTime);
207                 Long dur = (latestStopTime - latestStartTime) / 60000L;
208                 Log.v(TAG, "Chosen event: start " + stime +
209                         " for " + dur + " min");
210                 String minutes;
211                 String howlong = dur.toString();
212                 if (dur == 0) {
213                         howlong = lessthan;
214                         minutes = minutes2to4;
215                 } else if ((dur / 10) == 1) {
216                         minutes = minutes5up;
217                 } else if ((dur % 10) == 1) {
218                         minutes = minutes1;
219                 } else if ((dur % 10) < 5) {
220                         minutes = minutes2to4;
221                 } else {
222                         minutes = minutes5up;
223                 }
224                 return last_call +
225                         " " + (latestWasOutgoing?out_call:in_call) +
226                         " " + sayWhen.say(latestStartTime) +
227                         " " + duration + " " + howlong + " " + minutes;
228         }
229 }