package net.mvla.mvhs.schedulecalendar; import android.support.annotation.NonNull; import net.mvla.mvhs.schedulecalendar.bellschedule.BellSchedule; import net.mvla.mvhs.schedulecalendar.bellschedule.BellSchedulePeriod; import net.mvla.mvhs.schedulecalendar.sheet.Entry; import net.mvla.mvhs.schedulecalendar.sheet.RootSheetElement; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import biweekly.Biweekly; import biweekly.ICalendar; import biweekly.component.VEvent; import okhttp3.ResponseBody; import retrofit2.Retrofit; import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; import retrofit2.converter.moshi.MoshiConverterFactory; import retrofit2.http.GET; import rx.Single; public class ScheduleCalendarDataSource { @NonNull Single<ScheduleCalendarRepository.CalendarEvents> getCalendarEvents() { Retrofit restAdapter = new Retrofit.Builder() .baseUrl("https://www.google.com/calendar/ical/") .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); CalendarIcalService service = restAdapter.create(CalendarIcalService.class); return service.getCalendarFile() .flatMap(this::getEventListFromResponse) .map(vEvents -> { ScheduleCalendarRepository.CalendarEvents events = new ScheduleCalendarRepository.CalendarEvents(); events.events = vEvents; events.timestamp = System.currentTimeMillis(); return events; }); } Single<List<BellSchedule>> getBellSchedules() { return getBellScheduleSheet() .flatMap(this::parseSheetBellSchedules); } @NonNull private Single<List<Entry>> getBellScheduleSheet() { Retrofit restAdapter = new Retrofit.Builder() .baseUrl("https://spreadsheets.google.com/") .addConverterFactory(MoshiConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); SheetService service = restAdapter.create(SheetService.class); return service.getRootElement() .flatMap(rootSheetElement -> Single.create(singleSubscriber -> { singleSubscriber.onSuccess(rootSheetElement.getFeed().getEntry()); })); } @NonNull private Single<List<ScheduleCalendarRepository.Event>> getEventListFromResponse(ResponseBody calendarResponse) { return Single.create(subscriber -> { byte[] calBytes = new byte[0]; try { calBytes = calendarResponse.bytes(); } catch (IOException e) { subscriber.onError(e); } ICalendar calendar; try { calendar = Biweekly.parse(new ByteArrayInputStream(calBytes)).first(); } catch (IOException e) { subscriber.onError(e); return; } List<ScheduleCalendarRepository.Event> events = new ArrayList<>(); for (VEvent vEvent : calendar.getEvents()) { ScheduleCalendarRepository.Event event = new ScheduleCalendarRepository.Event(); event.startTime = vEvent.getDateStart().getValue().getTime(); event.endTime = vEvent.getDateEnd().getValue().getTime(); event.name = vEvent.getSummary().getValue(); events.add(event); } Collections.sort(events, (e1, e2) -> Double.compare(e1.startTime, e2.startTime)); subscriber.onSuccess(events); }); } @NonNull private Single<List<BellSchedule>> parseSheetBellSchedules(List<Entry> sheetEntries) { return Single.create(subscriber -> { List<BellSchedule> schedules = new ArrayList<>(); String periodName = null; for (Entry cell : sheetEntries) { String cellCoord = cell.getTitle().get$t(); String cellRow = cellCoord.substring(1); String cellCol = cellCoord.substring(0, 1); String cellContent = cell.getContent().get$t(); if (cellRow.equals("1")) { BellSchedule schedule = new BellSchedule(); schedule.name = cellContent; schedules.add(schedule); } else { if (cellCol.equals("A")) { periodName = cellContent; } else { BellSchedule schedule = schedules.get(cellCol.charAt(0) - 66); BellSchedulePeriod period = new BellSchedulePeriod(); String[] time = cellContent.split("[\\s:\\-]"); if (time.length == 4) { period.startHour = Integer.parseInt(time[0]); period.startMinute = Integer.parseInt(time[1]); period.endHour = Integer.parseInt(time[2]); period.endMinute = Integer.parseInt(time[3]); } if (period.startHour != 0) { period.name = periodName; schedule.addPeriod(period); } } } } for (BellSchedule schedule : schedules) { schedule.sort(); } subscriber.onSuccess(schedules); }); } private interface SheetService { @GET("feeds/cells/1BBGLmF4GgV7SjtZyfMANa6CVxr4-GY-_O1l1ZJX6Ooo/od6/public/basic?alt=json") Single<RootSheetElement> getRootElement(); } private interface CalendarIcalService { @GET("mvla.net_3236303434383738363838%40resource.calendar.google.com/public/basic.ics") Single<ResponseBody> getCalendarFile(); } }