package de.danoeh.antennapod.core.gpoddernet;

import android.support.annotation.NonNull;

import com.squareup.okhttp.Credentials;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
import com.squareup.okhttp.ResponseBody;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetDevice;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeAction;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeActionGetResponse;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeActionPostResponse;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetPodcast;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetSubscriptionChange;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetTag;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetUploadChangesResponse;
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;

/**
 * Communicates with the gpodder.net service.
 */
public class GpodnetService {

    private static final String TAG = "GpodnetService";

    private static final String BASE_SCHEME = "https";

    public static final String DEFAULT_BASE_HOST = "gpodder.net";
    private final String BASE_HOST;

    private static final MediaType TEXT = MediaType.parse("plain/text; charset=utf-8");
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");

    private final OkHttpClient httpClient;


    public GpodnetService() {
        httpClient = AntennapodHttpClient.getHttpClient();
        BASE_HOST = GpodnetPreferences.getHostname();
    }

    /**
     * Returns the [count] most used tags.
     */
    public List<GpodnetTag> getTopTags(int count)
            throws GpodnetServiceException {
        URL url;
        try {
            url = new URI(BASE_SCHEME, BASE_HOST, String.format(
                    "/api/2/tags/%d.json", count), null).toURL();
        } catch (MalformedURLException | URISyntaxException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        }

        Request.Builder request = new Request.Builder().url(url);
        String response = executeRequest(request);
        try {
            JSONArray jsonTagList = new JSONArray(response);
            List<GpodnetTag> tagList = new ArrayList<GpodnetTag>(
                    jsonTagList.length());
            for (int i = 0; i < jsonTagList.length(); i++) {
                JSONObject jObj = jsonTagList.getJSONObject(i);
                String title = jObj.getString("title");
                String tag = jObj.getString("tag");
                int usage = jObj.getInt("usage");
                tagList.add(new GpodnetTag(title, tag, usage));
            }
            return tagList;
        } catch (JSONException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        }
    }

    /**
     * Returns the [count] most subscribed podcasts for the given tag.
     *
     * @throws IllegalArgumentException if tag is null
     */
    public List<GpodnetPodcast> getPodcastsForTag(@NonNull GpodnetTag tag,
                                                  int count)
            throws GpodnetServiceException {
        try {
            URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
                    "/api/2/tag/%s/%d.json", tag.getTag(), count), null).toURL();
            Request.Builder request = new Request.Builder().url(url);
            String response = executeRequest(request);

            JSONArray jsonArray = new JSONArray(response);
            return readPodcastListFromJSONArray(jsonArray);

        } catch (JSONException | MalformedURLException | URISyntaxException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        }
    }

    /**
     * Returns the toplist of podcast.
     *
     * @param count of elements that should be returned. Must be in range 1..100.
     * @throws IllegalArgumentException if count is out of range.
     */
    public List<GpodnetPodcast> getPodcastToplist(int count)
            throws GpodnetServiceException {
        if(count < 1 || count > 100) {
            throw new IllegalArgumentException("Count must be in range 1..100");
        }

        try {
            URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
                    "/toplist/%d.json", count), null).toURL();
            Request.Builder request = new Request.Builder().url(url);
            String response = executeRequest(request);

            JSONArray jsonArray = new JSONArray(response);
            return readPodcastListFromJSONArray(jsonArray);

        } catch (JSONException | MalformedURLException | URISyntaxException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        }
    }

    /**
     * Returns a list of suggested podcasts for the user that is currently
     * logged in.
     * <p/>
     * This method requires authentication.
     *
     * @param count The
     *              number of elements that should be returned. Must be in range
     *              1..100.
     * @throws IllegalArgumentException              if count is out of range.
     * @throws GpodnetServiceAuthenticationException If there is an authentication error.
     */
    public List<GpodnetPodcast> getSuggestions(int count) throws GpodnetServiceException {
        if(count < 1 || count > 100) {
            throw new IllegalArgumentException("Count must be in range 1..100");
        }

        try {
            URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
                    "/suggestions/%d.json", count), null).toURL();
            Request.Builder request = new Request.Builder().url(url);
            String response = executeRequest(request);

            JSONArray jsonArray = new JSONArray(response);
            return readPodcastListFromJSONArray(jsonArray);
        } catch (JSONException | MalformedURLException | URISyntaxException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        }
    }

    /**
     * Searches the podcast directory for a given string.
     *
     * @param query          The search query
     * @param scaledLogoSize The size of the logos that are returned by the search query.
     *                       Must be in range 1..256. If the value is out of range, the
     *                       default value defined by the gpodder.net API will be used.
     */
    public List<GpodnetPodcast> searchPodcasts(String query, int scaledLogoSize)
            throws GpodnetServiceException {
        String parameters = (scaledLogoSize > 0 && scaledLogoSize <= 256) ? String
                .format("q=%s&scale_logo=%d", query, scaledLogoSize) : String
                .format("q=%s", query);
        try {
            URL url = new URI(BASE_SCHEME, null, BASE_HOST, -1, "/search.json",
                    parameters, null).toURL();
            Request.Builder request = new Request.Builder().url(url);
            String response = executeRequest(request);

            JSONArray jsonArray = new JSONArray(response);
            return readPodcastListFromJSONArray(jsonArray);

        } catch (JSONException | MalformedURLException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        } catch (URISyntaxException e) {
            e.printStackTrace();
            throw new IllegalStateException(e);
        }
    }

    /**
     * Returns all devices of a given user.
     * <p/>
     * This method requires authentication.
     *
     * @param username The username. Must be the same user as the one which is
     *                 currently logged in.
     * @throws IllegalArgumentException              If username is null.
     * @throws GpodnetServiceAuthenticationException If there is an authentication error.
     */
    public List<GpodnetDevice> getDevices(@NonNull String username)
            throws GpodnetServiceException {
        try {
            URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
                    "/api/2/devices/%s.json", username), null).toURL();
            Request.Builder request = new Request.Builder().url(url);
            String response = executeRequest(request);
            JSONArray devicesArray = new JSONArray(response);
            return readDeviceListFromJSONArray(devicesArray);
        } catch (JSONException | MalformedURLException | URISyntaxException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        }
    }

    /**
     * Configures the device of a given user.
     * <p/>
     * This method requires authentication.
     *
     * @param username The username. Must be the same user as the one which is
     *                 currently logged in.
     * @param deviceId The ID of the device that should be configured.
     * @throws IllegalArgumentException              If username or deviceId is null.
     * @throws GpodnetServiceAuthenticationException If there is an authentication error.
     */
    public void configureDevice(@NonNull String username,
                                @NonNull String deviceId,
                                String caption,
                                GpodnetDevice.DeviceType type)
            throws GpodnetServiceException {
        try {
            URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
                    "/api/2/devices/%s/%s.json", username, deviceId), null).toURL();
            String content;
            if (caption != null || type != null) {
                JSONObject jsonContent = new JSONObject();
                if (caption != null) {
                    jsonContent.put("caption", caption);
                }
                if (type != null) {
                    jsonContent.put("type", type.toString());
                }
                content = jsonContent.toString();
            } else {
                content = "";
            }
            RequestBody body = RequestBody.create(JSON, content);
            Request.Builder request = new Request.Builder().post(body).url(url);
            executeRequest(request);
        } catch (JSONException | MalformedURLException | URISyntaxException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        }
    }

    /**
     * Returns the subscriptions of a specific device.
     * <p/>
     * This method requires authentication.
     *
     * @param username The username. Must be the same user as the one which is
     *                 currently logged in.
     * @param deviceId The ID of the device whose subscriptions should be returned.
     * @return A list of subscriptions in OPML format.
     * @throws IllegalArgumentException              If username or deviceId is null.
     * @throws GpodnetServiceAuthenticationException If there is an authentication error.
     */
    public String getSubscriptionsOfDevice(@NonNull String username,
                                           @NonNull String deviceId)
            throws GpodnetServiceException {
        try {
            URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
                    "/subscriptions/%s/%s.opml", username, deviceId), null).toURL();
            Request.Builder request = new Request.Builder().url(url);
            return executeRequest(request);
        } catch (MalformedURLException | URISyntaxException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        }
    }

    /**
     * Returns all subscriptions of a specific user.
     * <p/>
     * This method requires authentication.
     *
     * @param username The username. Must be the same user as the one which is
     *                 currently logged in.
     * @return A list of subscriptions in OPML format.
     * @throws IllegalArgumentException              If username is null.
     * @throws GpodnetServiceAuthenticationException If there is an authentication error.
     */
    public String getSubscriptionsOfUser(@NonNull String username)
            throws GpodnetServiceException {

        try {
            URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
                    "/subscriptions/%s.opml", username), null).toURL();
            Request.Builder request = new Request.Builder().url(url);
            String response = executeRequest(request);
            return response;
        } catch (MalformedURLException | URISyntaxException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        }
    }

    /**
     * Uploads the subscriptions of a specific device.
     * <p/>
     * This method requires authentication.
     *
     * @param username      The username. Must be the same user as the one which is
     *                      currently logged in.
     * @param deviceId      The ID of the device whose subscriptions should be updated.
     * @param subscriptions A list of feed URLs containing all subscriptions of the
     *                      device.
     * @throws IllegalArgumentException              If username, deviceId or subscriptions is null.
     * @throws GpodnetServiceAuthenticationException If there is an authentication error.
     */
    public void uploadSubscriptions(@NonNull String username,
                                    @NonNull String deviceId,
                                    @NonNull List<String> subscriptions)
            throws GpodnetServiceException {

        try {
            URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
                    "/subscriptions/%s/%s.txt", username, deviceId), null).toURL();
            StringBuilder builder = new StringBuilder();
            for (String s : subscriptions) {
                builder.append(s);
                builder.append("\n");
            }
            RequestBody body = RequestBody.create(TEXT, builder.toString());
            Request.Builder request = new Request.Builder().put(body).url(url);
            executeRequest(request);
        } catch (MalformedURLException | URISyntaxException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        }

    }

    /**
     * Updates the subscription list of a specific device.
     * <p/>
     * This method requires authentication.
     *
     * @param username The username. Must be the same user as the one which is
     *                 currently logged in.
     * @param deviceId The ID of the device whose subscriptions should be updated.
     * @param added    Collection of feed URLs of added feeds. This Collection MUST NOT contain any duplicates
     * @param removed  Collection of feed URLs of removed feeds. This Collection MUST NOT contain any duplicates
     * @return a GpodnetUploadChangesResponse. See {@link de.danoeh.antennapod.core.gpoddernet.model.GpodnetUploadChangesResponse}
     * for details.
     * @throws java.lang.IllegalArgumentException                           if username, deviceId, added or removed is null.
     * @throws de.danoeh.antennapod.core.gpoddernet.GpodnetServiceException if added or removed contain duplicates or if there
     *                                                                      is an authentication error.
     */
    public GpodnetUploadChangesResponse uploadChanges(@NonNull String username,
                                                      @NonNull String deviceId,
                                                      @NonNull Collection<String> added,
                                                      @NonNull Collection<String> removed)
            throws GpodnetServiceException {

        try {
            URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
                    "/api/2/subscriptions/%s/%s.json", username, deviceId), null).toURL();

            final JSONObject requestObject = new JSONObject();
            requestObject.put("add", new JSONArray(added));
            requestObject.put("remove", new JSONArray(removed));

            RequestBody body = RequestBody.create(JSON, requestObject.toString());
            Request.Builder request = new Request.Builder().post(body).url(url);

            final String response = executeRequest(request);
            return GpodnetUploadChangesResponse.fromJSONObject(response);
        } catch (JSONException | MalformedURLException | URISyntaxException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        }

    }

    /**
     * Returns all subscription changes of a specific device.
     * <p/>
     * This method requires authentication.
     *
     * @param username  The username. Must be the same user as the one which is
     *                  currently logged in.
     * @param deviceId  The ID of the device whose subscription changes should be
     *                  downloaded.
     * @param timestamp A timestamp that can be used to receive all changes since a
     *                  specific point in time.
     * @throws IllegalArgumentException              If username or deviceId is null.
     * @throws GpodnetServiceAuthenticationException If there is an authentication error.
     */
    public GpodnetSubscriptionChange getSubscriptionChanges(@NonNull String username,
                                                            @NonNull String deviceId,
                                                            long timestamp) throws GpodnetServiceException {

        String params = String.format("since=%d", timestamp);
        String path = String.format("/api/2/subscriptions/%s/%s.json",
                username, deviceId);
        try {
            URL url = new URI(BASE_SCHEME, null, BASE_HOST, -1, path, params,
                    null).toURL();
            Request.Builder request = new Request.Builder().url(url);

            String response = executeRequest(request);
            JSONObject changes = new JSONObject(response);
            return readSubscriptionChangesFromJSONObject(changes);
        } catch (URISyntaxException e) {
            e.printStackTrace();
            throw new IllegalStateException(e);
        } catch (JSONException | MalformedURLException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        }

    }

    /**
     * Updates the episode actions
     * <p/>
     * This method requires authentication.
     *
     * @param episodeActions    Collection of episode actions.
     * @return a GpodnetUploadChangesResponse. See {@link de.danoeh.antennapod.core.gpoddernet.model.GpodnetUploadChangesResponse}
     * for details.
     * @throws java.lang.IllegalArgumentException                           if username, deviceId, added or removed is null.
     * @throws de.danoeh.antennapod.core.gpoddernet.GpodnetServiceException if added or removed contain duplicates or if there
     *                                                                      is an authentication error.
     */
    public GpodnetEpisodeActionPostResponse uploadEpisodeActions(@NonNull Collection<GpodnetEpisodeAction> episodeActions)
            throws GpodnetServiceException {

        String username = GpodnetPreferences.getUsername();

        try {
            URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
                    "/api/2/episodes/%s.json", username), null).toURL();

            final JSONArray list = new JSONArray();
            for(GpodnetEpisodeAction episodeAction : episodeActions) {
                JSONObject obj = episodeAction.writeToJSONObject();
                if(obj != null) {
                    list.put(obj);
                }
            }

            RequestBody body = RequestBody.create(JSON, list.toString());
            Request.Builder request = new Request.Builder().post(body).url(url);

            final String response = executeRequest(request);
            return GpodnetEpisodeActionPostResponse.fromJSONObject(response);
        } catch (JSONException | MalformedURLException | URISyntaxException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        }

    }

    /**
     * Returns all subscription changes of a specific device.
     * <p/>
     * This method requires authentication.
     *
     * @param timestamp A timestamp that can be used to receive all changes since a
     *                  specific point in time.
     * @throws IllegalArgumentException              If username or deviceId is null.
     * @throws GpodnetServiceAuthenticationException If there is an authentication error.
     */
    public GpodnetEpisodeActionGetResponse getEpisodeChanges(long timestamp) throws GpodnetServiceException {

        String username = GpodnetPreferences.getUsername();

        String params = String.format("since=%d", timestamp);
        String path = String.format("/api/2/episodes/%s.json",
                username);
        try {
            URL url = new URI(BASE_SCHEME, null, BASE_HOST, -1, path, params,
                    null).toURL();
            Request.Builder request = new Request.Builder().url(url);

            String response = executeRequest(request);
            JSONObject json = new JSONObject(response);
            return readEpisodeActionsFromJSONObject(json);
        } catch (URISyntaxException e) {
            e.printStackTrace();
            throw new IllegalStateException(e);
        } catch (JSONException | MalformedURLException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        }

    }


    /**
     * Logs in a specific user. This method must be called if any of the methods
     * that require authentication is used.
     *
     * @throws IllegalArgumentException If username or password is null.
     */
    public void authenticate(@NonNull String username,
                             @NonNull String password)
            throws GpodnetServiceException {
        URL url;
        try {
            url = new URI(BASE_SCHEME, BASE_HOST, String.format(
                    "/api/2/auth/%s/login.json", username), null).toURL();
        } catch (MalformedURLException | URISyntaxException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        }
        RequestBody body = RequestBody.create(TEXT, "");
        Request.Builder request = new Request.Builder().url(url).post(body);
        executeRequestWithAuthentication(request, username, password);
    }

    /**
     * Shuts down the GpodnetService's HTTP client. The service will be shut down in a separate thread to avoid
     * NetworkOnMainThreadExceptions.
     */
    public void shutdown() {
        new Thread() {
            @Override
            public void run() {
                AntennapodHttpClient.cleanup();
            }
        }.start();
    }

    private String executeRequest(@NonNull Request.Builder requestB)
            throws GpodnetServiceException {
        Request request = requestB.header("User-Agent", ClientConfig.USER_AGENT).build();
        String responseString = null;
        Response response = null;
        ResponseBody body = null;
        try {

            response = httpClient.newCall(request).execute();
            checkStatusCode(response);
            body = response.body();
            responseString = getStringFromResponseBody(body);
        } catch (IOException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        } finally {
            if (response != null && body != null) {
                try {
                    body.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new GpodnetServiceException(e);
                }
            }

        }
        return responseString;
    }

    private String executeRequestWithAuthentication(Request.Builder requestB,
                                                    String username, String password) throws GpodnetServiceException {
        if (requestB == null || username == null || password == null) {
            throw new IllegalArgumentException(
                    "request and credentials must not be null");
        }

        Request request = requestB.header("User-Agent", ClientConfig.USER_AGENT).build();
        String result = null;
        ResponseBody body = null;
        try {
            String credential = Credentials.basic(username, password);
            Request authRequest = request.newBuilder().header("Authorization", credential).build();
            Response response = httpClient.newCall(authRequest).execute();
            checkStatusCode(response);
            body = response.body();
            result = getStringFromResponseBody(body);
        } catch (Exception e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        } finally {
            if (body != null) {
                try {
                    body.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new GpodnetServiceException(e);
                }
            }
        }
        return result;
    }

    private String getStringFromResponseBody(@NonNull ResponseBody body)
            throws GpodnetServiceException {
        ByteArrayOutputStream outputStream;
        int contentLength = 0;
        try {
            contentLength = (int) body.contentLength();
        } catch (IOException ignore) {
            // ignore
        }
        if (contentLength > 0) {
            outputStream = new ByteArrayOutputStream(contentLength);
        } else {
            outputStream = new ByteArrayOutputStream();
        }
        try {
            byte[] buffer = new byte[8 * 1024];
            InputStream in = body.byteStream();
            int count;
            while ((count = in.read(buffer)) > 0) {
                outputStream.write(buffer, 0, count);
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new GpodnetServiceException(e);
        }
        return outputStream.toString();
    }

    private void checkStatusCode(@NonNull Response response)
            throws GpodnetServiceException {
        int responseCode = response.code();
        if (responseCode != HttpURLConnection.HTTP_OK) {
            if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
                throw new GpodnetServiceAuthenticationException("Wrong username or password");
            } else {
                throw new GpodnetServiceBadStatusCodeException("Bad response code: "
                        + responseCode, responseCode);
            }
        }
    }

    private List<GpodnetPodcast> readPodcastListFromJSONArray(@NonNull JSONArray array)
            throws JSONException {
        List<GpodnetPodcast> result = new ArrayList<GpodnetPodcast>(
                array.length());
        for (int i = 0; i < array.length(); i++) {
            result.add(readPodcastFromJSONObject(array.getJSONObject(i)));
        }
        return result;
    }

    private GpodnetPodcast readPodcastFromJSONObject(JSONObject object)
            throws JSONException {
        String url = object.getString("url");

        String title;
        Object titleObj = object.opt("title");
        if (titleObj != null && titleObj instanceof String) {
            title = (String) titleObj;
        } else {
            title = url;
        }

        String description;
        Object descriptionObj = object.opt("description");
        if (descriptionObj != null && descriptionObj instanceof String) {
            description = (String) descriptionObj;
        } else {
            description = "";
        }

        int subscribers = object.getInt("subscribers");

        Object logoUrlObj = object.opt("logo_url");
        String logoUrl = (logoUrlObj instanceof String) ? (String) logoUrlObj
                : null;
        if (logoUrl == null) {
            Object scaledLogoUrl = object.opt("scaled_logo_url");
            if (scaledLogoUrl != null && scaledLogoUrl instanceof String) {
                logoUrl = (String) scaledLogoUrl;
            }
        }

        String website = null;
        Object websiteObj = object.opt("website");
        if (websiteObj != null && websiteObj instanceof String) {
            website = (String) websiteObj;
        }
        String mygpoLink = object.getString("mygpo_link");
        return new GpodnetPodcast(url, title, description, subscribers,
                logoUrl, website, mygpoLink);
    }

    private List<GpodnetDevice> readDeviceListFromJSONArray(@NonNull JSONArray array)
            throws JSONException {
        List<GpodnetDevice> result = new ArrayList<GpodnetDevice>(
                array.length());
        for (int i = 0; i < array.length(); i++) {
            result.add(readDeviceFromJSONObject(array.getJSONObject(i)));
        }
        return result;
    }

    private GpodnetDevice readDeviceFromJSONObject(JSONObject object)
            throws JSONException {
        String id = object.getString("id");
        String caption = object.getString("caption");
        String type = object.getString("type");
        int subscriptions = object.getInt("subscriptions");
        return new GpodnetDevice(id, caption, type, subscriptions);
    }

    private GpodnetSubscriptionChange readSubscriptionChangesFromJSONObject(
            @NonNull JSONObject object) throws JSONException {

        List<String> added = new LinkedList<String>();
        JSONArray jsonAdded = object.getJSONArray("add");
        for (int i = 0; i < jsonAdded.length(); i++) {
            String addedUrl = jsonAdded.getString(i);
            // gpodder escapes colons unnecessarily
            addedUrl = addedUrl.replace("%3A", ":");
            added.add(addedUrl);
        }

        List<String> removed = new LinkedList<String>();
        JSONArray jsonRemoved = object.getJSONArray("remove");
        for (int i = 0; i < jsonRemoved.length(); i++) {
            String removedUrl = jsonRemoved.getString(i);
            // gpodder escapes colons unnecessarily
            removedUrl = removedUrl.replace("%3A", ":");
            removed.add(removedUrl);
        }

        long timestamp = object.getLong("timestamp");
        return new GpodnetSubscriptionChange(added, removed, timestamp);
    }

    private GpodnetEpisodeActionGetResponse readEpisodeActionsFromJSONObject(
            @NonNull JSONObject object) throws JSONException {

        List<GpodnetEpisodeAction> episodeActions = new ArrayList<GpodnetEpisodeAction>();

        long timestamp = object.getLong("timestamp");
        JSONArray jsonActions = object.getJSONArray("actions");
        for(int i=0; i < jsonActions.length(); i++) {
            JSONObject jsonAction = jsonActions.getJSONObject(i);
            GpodnetEpisodeAction episodeAction = GpodnetEpisodeAction.readFromJSONObject(jsonAction);
            if(episodeAction != null) {
                episodeActions.add(episodeAction);
            }
        }
        return new GpodnetEpisodeActionGetResponse(episodeActions, timestamp);
    }

}
