package org.fluxtream.connectors.fitbit;
import org.fluxtream.core.domain.AbstractFacet;
import org.fluxtream.core.domain.ApiKey;
import org.fluxtream.core.domain.ChannelMapping;
import org.fluxtream.core.services.impl.BodyTrackHelper;
import org.fluxtream.core.services.impl.FieldHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Candide Kemmler (candide@fluxtream.com)
*/
@Component("fitbitFoodLogSummary")
public class FitbitFoodLogSummaryFieldHandler implements FieldHandler {
private static final String DATASET_KEY = "dataset";
@Autowired
BodyTrackHelper bodyTrackHelper;
@Override
public List<BodyTrackHelper.BodyTrackUploadResult> handleField (final ApiKey apiKey, AbstractFacet facet) {
List<BodyTrackHelper.BodyTrackUploadResult> results = new ArrayList<BodyTrackHelper.BodyTrackUploadResult>();
FitbitFoodLogSummaryFacet fitbitFoodLogSummaryFacet = (FitbitFoodLogSummaryFacet) facet;
// The Fitbit activity data is daily data that covers an entire day. The start/end time may be the
// leading and trailing midnights for the date, or may both be at noon on the date, depending
// on the version that did the import. Either way they should now both be in UTC since
// it is a local time facet. Datastore points only have a single time associated with them.
// Set this time to be the middle value between start and end, which should be noon UTC in
// either case. Also convert to double seconds since that is what the datastore uses.
double dsTime = (double)(fitbitFoodLogSummaryFacet.start + fitbitFoodLogSummaryFacet.end)/2000.0;
List<String> channelNames = new ArrayList<String>();
List<List<Object>> data = new ArrayList<List<Object>>();
List<Object> record = new ArrayList<Object>();
// Add the timestamp to the start of the record
record.add(dsTime);
// Add each non-empty field to both the channelNames and data record so they correspond
if (fitbitFoodLogSummaryFacet.calories > 0) {
channelNames.add("caloriesIn");
record.add(fitbitFoodLogSummaryFacet.calories);
}
if (fitbitFoodLogSummaryFacet.water > 0) {
channelNames.add("water");
record.add(fitbitFoodLogSummaryFacet.water);
}
if (fitbitFoodLogSummaryFacet.caloriesGoal > 0) {
channelNames.add("caloriesInGoal");
record.add(fitbitFoodLogSummaryFacet.caloriesGoal);
}
if (fitbitFoodLogSummaryFacet.caloriesOutGoal > 0) {
channelNames.add("caloriesOutGoal");
record.add(fitbitFoodLogSummaryFacet.caloriesOutGoal);
}
data.add(record);
results.add(bodyTrackHelper.uploadToBodyTrack(apiKey, "Fitbit", channelNames, data));
// TODO: check the status code in the BodyTrackUploadResult
return results;
}
@Override
public void addToDeclaredChannelMappings(final ApiKey apiKey, final List<ChannelMapping> channelMappings) {
ChannelMapping.addToDeclaredMappings(apiKey, ChannelMapping.ChannelType.data, ChannelMapping.TimeType.local, 32, apiKey.getConnector().getDeviceNickname(), "caloriesIn", channelMappings);
ChannelMapping.addToDeclaredMappings(apiKey, ChannelMapping.ChannelType.data, ChannelMapping.TimeType.local, 32, apiKey.getConnector().getDeviceNickname(), "water", channelMappings);
ChannelMapping.addToDeclaredMappings(apiKey, ChannelMapping.ChannelType.data, ChannelMapping.TimeType.local, 32, apiKey.getConnector().getDeviceNickname(), "caloriesInGoal", channelMappings);
ChannelMapping.addToDeclaredMappings(apiKey, ChannelMapping.ChannelType.data, ChannelMapping.TimeType.local, 32, apiKey.getConnector().getDeviceNickname(), "caloriesOutGoal", channelMappings);
}
}