package org.fluxtream.connectors.lastfm;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import org.fluxtream.core.connectors.ObjectType;
import org.fluxtream.core.connectors.annotations.Updater;
import org.fluxtream.core.connectors.updaters.AbstractUpdater;
import org.fluxtream.core.connectors.updaters.UpdateInfo;
import org.fluxtream.core.domain.ApiKey;
import org.fluxtream.core.domain.ChannelMapping;
import org.fluxtream.core.services.JPADaoService;
import org.fluxtream.core.services.impl.BodyTrackHelper;
import org.fluxtream.core.utils.UnexpectedHttpResponseCodeException;
import org.fluxtream.core.utils.Utils;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import static org.fluxtream.core.utils.HttpUtils.fetch;
/**
* @author candide
*
*/
@Component
@Updater(prettyName = "Last FM", value = 10, objectTypes = {LastFmRecentTrackFacet.class}, extractor = LastFmFacetExtractor.class,
deviceNickname = "Last_FM",
bodytrackResponder = LastFmBodytrackResponder.class, defaultChannels = {"Last_FM.tracks"})
public class LastFmUpdater extends AbstractUpdater {
private static final int ITEMS_PER_PAGE = 200;
@Autowired
JPADaoService jpaDaoService;
@Autowired
BodyTrackHelper bodyTrackHelper;
public LastFmUpdater() {
super();
}
@Override
protected void updateConnectorDataHistory(UpdateInfo updateInfo) throws Exception {
final ObjectType recent_track = ObjectType.getObjectType(connector(), "recent_track");
if (updateInfo.objectTypes().contains(recent_track)) {
retrieveTracks(updateInfo, 0, "recenttracks");
}
}
@Override
public void updateConnectorData(UpdateInfo updateInfo) throws Exception {
if (updateInfo.objectTypes().contains(ObjectType.getObjectType(connector(), "recent_track"))) {
retrieveRecentTracks(updateInfo);
}
}
@Override
public void setDefaultChannelStyles(ApiKey apiKey) {
BodyTrackHelper.ChannelStyle channelStyle = new BodyTrackHelper.ChannelStyle();
channelStyle.timespanStyles = new BodyTrackHelper.MainTimespanStyle();
channelStyle.timespanStyles.defaultStyle = new BodyTrackHelper.TimespanStyle();
channelStyle.timespanStyles.defaultStyle.fillColor = "#fd4938";
channelStyle.timespanStyles.defaultStyle.borderColor = "#fd4938";
channelStyle.timespanStyles.defaultStyle.borderWidth = 2;
channelStyle.timespanStyles.defaultStyle.top = 0.0;
channelStyle.timespanStyles.defaultStyle.bottom = 1.0;
channelStyle.timespanStyles.values = new HashMap();
BodyTrackHelper.TimespanStyle stylePart = new BodyTrackHelper.TimespanStyle();
stylePart.top = 0.25;
stylePart.bottom = 0.75;
stylePart.fillColor = "#fd4938";
stylePart.borderColor = "#fd4938";
channelStyle.timespanStyles.values.put("on",stylePart);
bodyTrackHelper.setBuiltinDefaultStyle(apiKey.getGuestId(), apiKey.getConnector().getName(), "tracks", channelStyle);
}
private void retrieveTracks(final UpdateInfo updateInfo, final long fromTime, final String tracksType) throws Exception {
int page = 0;
do {
JSONObject tracks = getTracks(updateInfo, fromTime, System.currentTimeMillis(), page, tracksType);
JSONObject tracksObject = tracks.getJSONObject(tracksType);
if (tracksObject.containsKey("track") && (tracksObject.get("track") instanceof JSONArray
|| tracksObject.get("track") instanceof JSONObject))
apiDataService.cacheApiDataJSON(updateInfo, tracks, -1, -1);
else
return;
final JSONObject metadata = tracksObject.getJSONObject("@attr");
final int currentPage = Integer.valueOf(metadata.getString("page"));
final int totalPages = Integer.valueOf(metadata.getString("totalPages"));
if (totalPages-1 == currentPage)
break;
page++;
} while (true);
}
private void retrieveRecentTracks(UpdateInfo updateInfo) throws Exception {
LastFmRecentTrackFacet lastRetrievedTrack = jpaDaoService.findOne("lastfm.recent_track.newest", LastFmRecentTrackFacet.class, updateInfo.apiKey.getId());
long fromTime = 0;
if (lastRetrievedTrack != null) {
fromTime = lastRetrievedTrack.time;
}
retrieveTracks(updateInfo, fromTime, "recenttracks");
}
private JSONObject getTracks(UpdateInfo updateInfo, long from, long to, int page, String tracksType) throws Exception {
String api_key = guestService.getApiKeyAttribute(updateInfo.apiKey, "lastfmConsumerKey");
String username = guestService.getApiKeyAttribute(updateInfo.apiKey, "username");
long then = System.currentTimeMillis();
String query = String.format("http://ws.audioscrobbler.com/2.0/?method=user.get%s&user=%s&from=%s&to=%s&api_key=%s&limit=%s&format=%s&page=%s",
tracksType, username, from/1000, to/1000, api_key, ITEMS_PER_PAGE, "json", page);
try {
String tracksJson = fetch(query);
countSuccessfulApiCall(updateInfo.apiKey, updateInfo.objectTypes, then, query);
JSONObject result = JSONObject.fromObject(tracksJson);
return result;
}
catch (UnexpectedHttpResponseCodeException e) {
countFailedApiCall(updateInfo.apiKey, updateInfo.objectTypes, then, query, Utils.stackTrace(e),
e.getHttpResponseCode(), e.getHttpResponseMessage());
throw e;
} catch (IOException e) {
reportFailedApiCall(updateInfo.apiKey, updateInfo.objectTypes, then, query, Utils.stackTrace(e), "I/O");
throw e;
}
}
}