package nl.topicus.onderwijs.dashboard.modules.google;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import nl.topicus.onderwijs.dashboard.config.ISettings;
import nl.topicus.onderwijs.dashboard.datasources.Events;
import nl.topicus.onderwijs.dashboard.datatypes.Event;
import nl.topicus.onderwijs.dashboard.keys.AbstractCodeNameKey;
import nl.topicus.onderwijs.dashboard.keys.Key;
import nl.topicus.onderwijs.dashboard.modules.AbstractService;
import nl.topicus.onderwijs.dashboard.modules.DashboardRepository;
import nl.topicus.onderwijs.dashboard.modules.ServiceConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.google.gdata.client.calendar.CalendarQuery;
import com.google.gdata.client.calendar.CalendarService;
import com.google.gdata.data.DateTime;
import com.google.gdata.data.calendar.CalendarEntry;
import com.google.gdata.data.calendar.CalendarEventEntry;
import com.google.gdata.data.calendar.CalendarEventFeed;
import com.google.gdata.data.calendar.CalendarFeed;
import com.google.gdata.data.extensions.When;
@Service
@ServiceConfiguration(interval = 1, unit = TimeUnit.MINUTES)
public class GoogleEventService extends AbstractService {
private static final Logger log = LoggerFactory
.getLogger(GoogleEventService.class);
private static final Pattern TAG_PATTERN = Pattern.compile("#\\w*");
private List<Event> events = new ArrayList<Event>();
@Autowired
public GoogleEventService(ISettings settings) {
super(settings);
}
@Override
public void onConfigure(DashboardRepository repository) {
Map<Key, Map<String, ?>> serviceSettings = getSettings()
.getServiceSettings(GoogleEventService.class);
for (Map.Entry<Key, Map<String, ?>> curSettingEntry : serviceSettings
.entrySet()) {
repository.addDataSource(curSettingEntry.getKey(), Events.class,
new EventsImpl(curSettingEntry.getKey(), this));
if (curSettingEntry.getKey() instanceof AbstractCodeNameKey) {
AbstractCodeNameKey colorkey = ((AbstractCodeNameKey) curSettingEntry
.getKey());
if (colorkey.getColor() == null) {
try {
Map<String, ?> googleSettingsForProject = curSettingEntry
.getValue();
String username = googleSettingsForProject.get(
"username").toString();
String password = googleSettingsForProject.get(
"password").toString();
String calendarId = googleSettingsForProject.get(
"calendarId").toString();
CalendarService service = new CalendarService(
"Dashboard");
service.setUserCredentials(username, password);
CalendarQuery calendarQuery = new CalendarQuery(
new URL(
"https://www.google.com/calendar/feeds/default/owncalendars/full"));
CalendarFeed calendarFeed = service.query(
calendarQuery, CalendarFeed.class);
for (CalendarEntry curCalendar : calendarFeed
.getEntries()) {
if (curCalendar.getId().endsWith(
calendarId.replaceAll("@", "%40"))
&& curCalendar.getColor() != null) {
colorkey.setColor(curCalendar.getColor()
.getValue());
break;
}
}
} catch (Exception e) {
log.error("Unable to fetch color codes from google: "
+ e.getClass().getSimpleName(), e);
}
}
}
}
}
@Override
public void refreshData() {
try {
Map<Key, Map<String, ?>> serviceSettings = getSettings()
.getServiceSettings(GoogleEventService.class);
List<Event> ret = new ArrayList<Event>();
for (Map.Entry<Key, Map<String, ?>> curSettingEntry : serviceSettings
.entrySet()) {
Map<String, ?> googleSettingsForProject = curSettingEntry
.getValue();
String username = googleSettingsForProject.get("username")
.toString();
String password = googleSettingsForProject.get("password")
.toString();
String calendarId = googleSettingsForProject.get("calendarId")
.toString();
CalendarService service = new CalendarService("Dashboard");
service.setUserCredentials(username, password);
URL feedUrl = new URL("http://www.google.com/calendar/feeds/"
+ calendarId + "/private/full");
try {
CalendarQuery myQuery = new CalendarQuery(feedUrl);
Calendar cal = Calendar.getInstance();
myQuery.setMinimumStartTime(dateToGDateTime(cal.getTime()));
cal.add(Calendar.MONTH, 3);
myQuery.setMaximumStartTime(dateToGDateTime(cal.getTime()));
cal.add(Calendar.MONTH, -2);
myQuery.setMaxResults(100);
myQuery.setIntegerCustomParameter("max-results", 100);
// Send the request and receive the response:
CalendarEventFeed resultFeed = service.query(myQuery,
CalendarEventFeed.class);
for (CalendarEventEntry eventEntry : resultFeed
.getEntries()) {
for (When curTime : eventEntry.getTimes()) {
Event event = new Event();
event.setKey(curSettingEntry.getKey());
event.setTitle(eventEntry.getTitle().getPlainText());
// event.setOmschrijving(entry.getPlainTextContent());
event.setDateTime(gDateTimeToDate(curTime
.getStartTime()));
if (curSettingEntry.getKey() instanceof AbstractCodeNameKey)
event.setColor(((AbstractCodeNameKey) curSettingEntry
.getKey()).getColor());
Matcher m = TAG_PATTERN.matcher(eventEntry
.getPlainTextContent());
while (m.find()) {
String curTag = m.group();
event.getTags().add(curTag);
if ("#major".equals(curTag))
event.setMajor(true);
}
if (event.isMajor()
|| event.getDateTime()
.before(cal.getTime()))
ret.add(event);
}
}
} catch (Exception e) {
log.error("Unable to refresh data from google for "
+ calendarId + ": " + e.getClass().getSimpleName(),
e);
}
}
events = ret;
} catch (Exception e) {
log.error("Unable to refresh data from google: "
+ e.getClass().getSimpleName(), e);
}
}
private Date gDateTimeToDate(DateTime dateTime) {
Calendar cal = new GregorianCalendar();
cal.setTimeInMillis(dateTime.getValue());
if (dateTime.isDateOnly()) {
cal.add(Calendar.MILLISECOND,
-cal.getTimeZone().getOffset(cal.getTimeInMillis()));
}
return cal.getTime();
}
private DateTime dateToGDateTime(Date date) {
Calendar cal = new GregorianCalendar();
cal.setTime(date);
cal.add(Calendar.MILLISECOND,
cal.getTimeZone().getOffset(cal.getTimeInMillis()));
return new DateTime(cal.getTime());
}
public List<Event> getEvents(Key key) {
List<Event> ret = new ArrayList<Event>();
for (Event curEvent : events) {
if (curEvent.getKey().equals(key))
ret.add(curEvent);
}
return ret;
}
}