class DexcomAdapterService implements AdapterService<DexcomSyncData> {

  @Override
  public SyncData convertData(DexcomSyncData source) {
    List<GlucoseRead> glucoseReads = newArrayList(Collections2.filter(Collections2.transform(source.getGlucoseReads(),
        DEXCOM_GLUCOSE_RECORD_TO_GLUCOSE_READ), VALID_READS_FILTER));

    DeviceInfo deviceInfo = DEXCOM_MANUFACTURING_PARAMS_TO_DEVICE_INFO.apply(source.getManufacturingParameters());

    Collection<UserEventRecord> insulinEvents = Collections2.filter(source.getUserEvents(), INSULIN_EVENT_FILTER);
    Collection<UserEventRecord> exerciseEvents = Collections2.filter(source.getUserEvents(), EXERCISE_EVENT_FILTER);
    Collection<UserEventRecord> carbEvents = Collections2.filter(source.getUserEvents(), CARB_EVENT_FILTER);

    List<InsulinInjection> injections =
        newArrayList(Collections2.transform(insulinEvents, USER_EVENT_RECORD_TO_INSULIN_INJECTION));
    List<ExerciseSession> exerciseSessions =
        newArrayList(Collections2.transform(exerciseEvents, USER_EVENT_RECORD_TO_EXERCISE_SESSION));
    List<FoodEvent> foodEvents =
        newArrayList(Collections2.transform(carbEvents, USER_EVENT_RECORD_TO_FOOD_EVENT));

    return new SyncData(glucoseReads, injections, foodEvents, exerciseSessions, deviceInfo, source.getUpdateTime());
  }

}

class TestDexcomAdapterService {

  private static final String SERIAL_NUMBER;
  private static final String HARDWARE_REVISION;
  private static final String HARDWARE_ID;
  private static final Integer NORMAL_READ_TEST_VALUE;
  private static final List<GlucoseRead> EMPTY_GLUCOSE_READS;
  private static final List<GlucoseReadRecord> EMPTY_GLUCOSE_READ_RECORDS;
  private static final List<InsulinInjection> EMPTY_INSULIN_INJECTIONS;
  private static final List<UserEventRecord> EMPTY_USER_EVENT_RECORDS;
  private static final List<FoodEvent> EMPTY_FOOD_EVENTS;
  private static final List<ExerciseSession> EMPTY_EXERCISE_SESSIONS;
  private static final Instant TEST_TIME;

  @Test
  public void multipleReadsShouldAllBeConverted() throws Exception {

    DexcomAdapterService dexcomAdapterService = new DexcomAdapterService();
    List<GlucoseReadRecord> glucoseRecords = Arrays.asList(new GlucoseReadRecord(1000, 1000, NORMAL_READ_TEST_VALUE, (byte) 0, 1L, 1L),
        new GlucoseReadRecord(2000, 2000, NORMAL_READ_TEST_VALUE, (byte) 0, 1L, 1L));
    SyncData syncData = dexcomAdapterService.convertData(new DexcomSyncData(glucoseRecords, EMPTY_USER_EVENT_RECORDS,
        new ManufacturingParameters(SERIAL_NUMBER, "partNumber", HARDWARE_REVISION, "2013-10-18 10:10", HARDWARE_ID),
            TEST_TIME));

    GlucoseRead expectedRead1 = new GlucoseRead(
        internalTimeFromSeconds(1000L),
        localDateTimeFromSeconds(1000L),
        NORMAL_READ_TEST_VALUE.floatValue(),
        GlucoseRead.Unit.MG_PER_DL);

    GlucoseRead expectedRead2 = new GlucoseRead(
        internalTimeFromSeconds(2000L),
        localDateTimeFromSeconds(2000L),
        NORMAL_READ_TEST_VALUE.floatValue(),
        GlucoseRead.Unit.MG_PER_DL);
    SyncData expectedSyncData = new SyncData(Arrays.asList(expectedRead1, expectedRead2), EMPTY_INSULIN_INJECTIONS,
        EMPTY_FOOD_EVENTS, EMPTY_EXERCISE_SESSIONS, new DeviceInfo(SERIAL_NUMBER, HARDWARE_ID, HARDWARE_REVISION),
            TEST_TIME);

    assertThat(syncData, is(equalTo(expectedSyncData)));
  }

}