package de.danoeh.antennapod.core.gpoddernet.model;
import android.text.TextUtils;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
import de.danoeh.antennapod.core.util.DateUtils;
public class GpodnetEpisodeAction {
private static final String TAG = "GpodnetEpisodeAction";
public enum Action {
NEW, DOWNLOAD, PLAY, DELETE
}
private final String podcast;
private final String episode;
private final String deviceId;
private final Action action;
private final Date timestamp;
private final int started;
private final int position;
private final int total;
private GpodnetEpisodeAction(Builder builder) {
this.podcast = builder.podcast;
this.episode = builder.episode;
this.action = builder.action;
this.deviceId = builder.deviceId;
this.timestamp = builder.timestamp;
this.started = builder.started;
this.position = builder.position;
this.total = builder.total;
}
/**
* Creates an episode action object from a String representation. The representation includes
* all mandatory and optional attributes
*
* @param s String representation (output from {@link #writeToString()})
* @return episode action object, or null if s is invalid
*/
public static GpodnetEpisodeAction readFromString(String s) {
String[] fields = s.split("\t");
if(fields.length != 8) {
return null;
}
String podcast = fields[0];
String episode = fields[1];
String deviceId = fields[2];
try {
Action action = Action.valueOf(fields[3]);
return new Builder(podcast, episode, action)
.deviceId(deviceId)
.timestamp(new Date(Long.parseLong(fields[4])))
.started(Integer.parseInt(fields[5]))
.position(Integer.parseInt(fields[6]))
.total(Integer.parseInt(fields[7]))
.build();
} catch(IllegalArgumentException e) {
Log.e(TAG, "readFromString(" + s + "): " + e.getMessage());
return null;
}
}
/**
* Create an episode action object from JSON representation. Mandatory fields are "podcast",
* "episode" and "action".
*
* @param object JSON representation
* @return episode action object, or null if mandatory values are missing
*/
public static GpodnetEpisodeAction readFromJSONObject(JSONObject object) {
String podcast = object.optString("podcast", null);
String episode = object.optString("episode", null);
String actionString = object.optString("action", null);
if(TextUtils.isEmpty(podcast) || TextUtils.isEmpty(episode) || TextUtils.isEmpty(actionString)) {
return null;
}
GpodnetEpisodeAction.Action action;
try {
action = GpodnetEpisodeAction.Action.valueOf(actionString.toUpperCase());
} catch (IllegalArgumentException e) {
return null;
}
String deviceId = object.optString("device", "");
GpodnetEpisodeAction.Builder builder = new GpodnetEpisodeAction.Builder(podcast, episode, action)
.deviceId(deviceId);
String utcTimestamp = object.optString("timestamp", null);
if(!TextUtils.isEmpty(utcTimestamp)) {
builder.timestamp(DateUtils.parse(utcTimestamp));
}
if(action == GpodnetEpisodeAction.Action.PLAY) {
int started = object.optInt("started", -1);
int position = object.optInt("position", -1);
int total = object.optInt("total", -1);
if(started >= 0 && position > 0 && total > 0) {
builder
.started(started)
.position(position)
.total(total);
}
}
return builder.build();
}
public String getPodcast() {
return this.podcast;
}
public String getEpisode() {
return this.episode;
}
public String getDeviceId() {
return this.deviceId;
}
public Action getAction() {
return this.action;
}
public String getActionString() {
return this.action.name().toLowerCase();
}
public Date getTimestamp() {
return this.timestamp;
}
/**
* Returns the position (in seconds) at which the client started playback
*
* @return start position (in seconds)
*/
public int getStarted() {
return this.started;
}
/**
* Returns the position (in seconds) at which the client stopped playback
*
* @return stop position (in seconds)
*/
public int getPosition() {
return this.position;
}
/**
* Returns the total length of the file in seconds.
*
* @return total length in seconds
*/
public int getTotal() {
return this.total;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GpodnetEpisodeAction that = (GpodnetEpisodeAction) o;
if (started != that.started) return false;
if (position != that.position) return false;
if (total != that.total) return false;
if (podcast != null ? !podcast.equals(that.podcast) : that.podcast != null) return false;
if (episode != null ? !episode.equals(that.episode) : that.episode != null) return false;
if (deviceId != null ? !deviceId.equals(that.deviceId) : that.deviceId != null)
return false;
if (action != that.action) return false;
return !(timestamp != null ? !timestamp.equals(that.timestamp) : that.timestamp != null);
}
@Override
public int hashCode() {
int result = podcast != null ? podcast.hashCode() : 0;
result = 31 * result + (episode != null ? episode.hashCode() : 0);
result = 31 * result + (deviceId != null ? deviceId.hashCode() : 0);
result = 31 * result + (action != null ? action.hashCode() : 0);
result = 31 * result + (timestamp != null ? timestamp.hashCode() : 0);
result = 31 * result + started;
result = 31 * result + position;
result = 31 * result + total;
return result;
}
public String writeToString() {
StringBuilder result = new StringBuilder();
result.append(this.podcast).append("\t");
result.append(this.episode).append("\t");
result.append(this.deviceId).append("\t");
result.append(this.action).append("\t");
result.append(this.timestamp.getTime()).append("\t");
result.append(String.valueOf(this.started)).append("\t");
result.append(String.valueOf(this.position)).append("\t");
result.append(String.valueOf(this.total));
return result.toString();
}
/**
* Returns a JSON object representation of this object
*
* @return JSON object representation, or null if the object is invalid
*/
public JSONObject writeToJSONObject() {
JSONObject obj = new JSONObject();
try {
obj.putOpt("podcast", this.podcast);
obj.putOpt("episode", this.episode);
obj.put("device", this.deviceId);
obj.put("action", this.getActionString());
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US);
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
obj.put("timestamp",formatter.format(this.timestamp));
if (this.getAction() == Action.PLAY) {
obj.put("started", this.started);
obj.put("position", this.position);
obj.put("total", this.total);
}
} catch(JSONException e) {
Log.e(TAG, "writeToJSONObject(): " + e.getMessage());
return null;
}
return obj;
}
@Override
public String toString() {
return "GpodnetEpisodeAction{" +
"podcast='" + podcast + '\'' +
", episode='" + episode + '\'' +
", deviceId='" + deviceId + '\'' +
", action=" + action +
", timestamp=" + timestamp +
", started=" + started +
", position=" + position +
", total=" + total +
'}';
}
public static class Builder {
// mandatory
private final String podcast;
private final String episode;
private final Action action;
// optional
private String deviceId = "";
private Date timestamp;
private int started = -1;
private int position = -1;
private int total = -1;
public Builder(FeedItem item, Action action) {
this(item.getFeed().getDownload_url(), item.getMedia().getDownload_url(), action);
}
public Builder(String podcast, String episode, Action action) {
this.podcast = podcast;
this.episode = episode;
this.action = action;
}
public Builder deviceId(String deviceId) {
this.deviceId = deviceId;
return this;
}
public Builder currentDeviceId() {
return deviceId(GpodnetPreferences.getDeviceID());
}
public Builder timestamp(Date timestamp) {
this.timestamp = timestamp;
return this;
}
public Builder currentTimestamp() {
return timestamp(new Date());
}
public Builder started(int seconds) {
if(action == Action.PLAY) {
this.started = seconds;
}
return this;
}
public Builder position(int seconds) {
if(action == Action.PLAY) {
this.position = seconds;
}
return this;
}
public Builder total(int seconds) {
if(action == Action.PLAY) {
this.total = seconds;
}
return this;
}
public GpodnetEpisodeAction build() {
return new GpodnetEpisodeAction(this);
}
}
}