package org.fluxtream.connectors.moves;
import org.fluxtream.core.Configuration;
import org.fluxtream.core.SimpleTimeInterval;
import org.fluxtream.core.TimeInterval;
import org.fluxtream.core.TimeUnit;
import org.fluxtream.core.connectors.Connector;
import org.fluxtream.core.connectors.ObjectType;
import org.fluxtream.core.connectors.bodytrackResponders.AbstractBodytrackResponder;
import org.fluxtream.core.connectors.vos.AbstractFacetVO;
import org.fluxtream.core.domain.AbstractFacet;
import org.fluxtream.core.domain.ApiKey;
import org.fluxtream.core.domain.ChannelMapping;
import org.fluxtream.core.domain.GuestSettings;
import org.fluxtream.core.domain.metadata.FoursquareVenue;
import org.fluxtream.core.mvc.models.TimespanModel;
import org.fluxtream.core.services.JPADaoService;
import org.fluxtream.core.services.impl.BodyTrackHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.ws.rs.PathParam;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.TimeZone;
@Component
public class MovesBodytrackResponder extends AbstractBodytrackResponder {
@Autowired
Configuration env;
@Autowired
JPADaoService jpaDaoService;
@Override
public List<TimespanModel> getTimespans(final long startMillis, final long endMillis, final ApiKey apiKey, final String channelName) {
List<TimespanModel> items = new ArrayList<TimespanModel>();
final TimeInterval timeInterval = new SimpleTimeInterval(startMillis, endMillis, TimeUnit.ARBITRARY, TimeZone.getTimeZone("UTC"));
ObjectType[] objectTypes = apiKey.getConnector().objectTypes();
//TODO: support merging
for (ObjectType objectType : objectTypes){
String objectTypeName = apiKey.getConnector().getName() + "-" + objectType.getName();
if (objectType.getName().equals("move")){
List<AbstractFacet> facets = getFacetsInTimespan(timeInterval,apiKey,objectType);
for (AbstractFacet facet : facets){
MovesMoveFacet moveFacet = (MovesMoveFacet) facet;
for (MovesActivity activity : moveFacet.getActivities()){
BodyTrackHelper.TimespanStyle style = new BodyTrackHelper.TimespanStyle();
style.iconURL = String.format(env.get("homeBaseUrl")+"%s/images/moves/" + activity.activity + ".png", env.get("release"));
final TimespanModel moveTimespanModel = new TimespanModel(activity.start, activity.end, activity.activity, objectTypeName, style);
items.add(moveTimespanModel);
}
}
}
else if (objectType.getName().equals("place")){
List<AbstractFacet> facets = getFacetsInTimespan(timeInterval,apiKey,objectType);
for (AbstractFacet facet : facets){
MovesPlaceFacet place = (MovesPlaceFacet) facet;
BodyTrackHelper.TimespanStyle style = new BodyTrackHelper.TimespanStyle();
style.iconURL = getMovesPlaceIcon(place.apiKeyId, place.getId());
final TimespanModel placeTimespanModel = new TimespanModel(place.start, place.end, "place", objectTypeName,style);
items.add(placeTimespanModel);
}
}
}
return items;
}
public String getMovesPlaceIcon(@PathParam("apiKeyId") long apiKeyId,
@PathParam("id") long id) {
List l = jpaDaoService.executeNativeQuery("SELECT type, foursquareId FROM Facet_MovesPlace WHERE apiKeyId=(?1) AND id=(?2)", apiKeyId, id);
String homeBaseUrl = env.get("homeBaseUrl");
if (l==null||l.size()==0)
return homeBaseUrl+"images/moves/unknown.png";
final Object[] singleResult = (Object[])l.get(0);
String type = (String) singleResult[0];
if (type.equals("foursquare")) {
String foursquareId = (String) singleResult[1];
final FoursquareVenue foursquareVenue = metadataService.getFoursquareVenue(foursquareId);
return foursquareVenue.categoryIconUrlPrefix + "bg_32" + foursquareVenue.categoryIconUrlSuffix;
} else {
return homeBaseUrl+"images/moves/" + type + ".png";
}
}
@Override
public List<AbstractFacetVO<AbstractFacet>> getFacetVOs(final GuestSettings guestSettings, final ApiKey apiKey, final String objectTypeName, final long start, final long end, final String value) {
Connector connector = apiKey.getConnector();
String[] objectTypeNameParts = objectTypeName.split("-");
ObjectType objectType = null;
for (ObjectType ot : connector.objectTypes()){
if (ot.getName().equals(objectTypeNameParts[1])){
objectType = ot;
break;
}
}
if (objectType == null || (objectType.getName().equals("place") && !"place".equals(value)))
return new ArrayList<AbstractFacetVO<AbstractFacet>>();
TimeInterval timeInterval = metadataService.getArbitraryTimespanMetadata(apiKey.getGuestId(), start, end).getTimeInterval();
List<AbstractFacet> facets = getFacetsInTimespan(timeInterval,apiKey,objectType);
if (objectType.getName().equals("move")){
MovesMoveFacet move;
for (Iterator<AbstractFacet> i = facets.iterator(); i.hasNext();){
move = (MovesMoveFacet) i.next();
boolean found = false;
for (MovesActivity activity : move.getActivities()){
if (activity.activity.equals(value)){
found = true;
break;
}
}
if (!found)
i.remove();
}
}
List<AbstractFacetVO<AbstractFacet>> facetVOsForFacets = getFacetVOsForFacets(facets, timeInterval, guestSettings);
facetVOsForFacets = dedup(facetVOsForFacets);
return facetVOsForFacets;
}
private List<AbstractFacetVO<AbstractFacet>> dedup(final List<AbstractFacetVO<AbstractFacet>> facetVOs) {
List<AbstractFacetVO<AbstractFacet>> deduped = new ArrayList<AbstractFacetVO<AbstractFacet>>();
there: for (AbstractFacetVO<AbstractFacet> facetVO : facetVOs) {
AbstractMovesFacetVO f = (AbstractMovesFacetVO) facetVO;
for (AbstractFacetVO<AbstractFacet> uniqueFacet : deduped) {
AbstractMovesFacetVO u = (AbstractMovesFacetVO) uniqueFacet;
if (u.type.equals(f.type)&&u.start==f.start) {
if (u.end>f.end)
continue there;
else {
deduped.remove(u);
deduped.add(f);
continue there;
}
}
}
deduped.add(f);
}
return deduped;
}
public void addToDeclaredChannelMappings(final ApiKey apiKey, final List<ChannelMapping> channelMappings) {
ChannelMapping movesDataChannelMapping = new ChannelMapping(
apiKey.getId(), apiKey.getGuestId(),
ChannelMapping.ChannelType.timespan,
ChannelMapping.TimeType.gmt,
ObjectType.getObjectType(apiKey.getConnector(), "move").value() + ObjectType.getObjectType(apiKey.getConnector(), "place").value(),
apiKey.getConnector().getDeviceNickname(), "data",
apiKey.getConnector().getDeviceNickname(), "data");
channelMappings.add(movesDataChannelMapping);
}
}