package io.github.xwz.iview.api;
import android.content.Context;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import io.github.xwz.base.ImmutableMap;
import io.github.xwz.base.api.EpisodeBaseModel;
import io.github.xwz.iview.content.ContentManager;
public class TvShowListApi extends IViewApi {
private static final String TAG = "TvShowListApi";
private static final int CACHE_EXPIRY = 600; // 10 mins
private final Map<String, EpisodeBaseModel> episodes = new HashMap<>();
private final List<EpisodeBaseModel> shows = new ArrayList<>();
private LinkedHashMap<String, List<EpisodeBaseModel>> collections = new LinkedHashMap<>();
private boolean success = false;
public TvShowListApi(Context context) {
super(context);
}
private int progress = 0;
private static final String[] PROGRESS = new String[]{
"Loading ABC1...", "Loading ABC2...", "Loading ABC3...", "Loading ABC4Kids...", "Loading News...",
"Loading Comedy...", "Loading Documentaries...", "Loading Drama...", "Loading Arts...", "Loading Education...",
"Loading Lifestyle...", "Loading Sports...",
};
@Override
protected Void doInBackground(String... urls) {
if (ContentManager.db().loadFromDbCache(ContentManager.cache(), EpisodeModel.class)) {
ContentManager.getInstance().broadcastChange(ContentManager.CONTENT_SHOW_LIST_DONE);
}
updateProgress();
fetchTitlesFromCollection();
for (String cat : ContentManager.CATEGORIES.keySet()) {
updateProgress();
fetchTitlesInCategory(cat);
}
Log.d(TAG, "Found " + episodes.size() + " episodes from category query");
fetchTitlesFromIndex();
updateProgress();
ContentManager.cache().putShows(shows);
ContentManager.cache().putEpisodes(episodes.values());
ContentManager.cache().putCollections(collections);
ContentManager.cache().buildDictionary(shows);
ContentManager.db().clearCache();
ContentManager.db().putShows(shows);
updateProgress();
ContentManager.db().putEpisodes(episodes.values());
updateProgress();
ContentManager.db().putCollections(collections);
updateProgress();
Log.d(TAG, "DONE");
success = true;
return null;
}
private void updateProgress() {
ContentManager.getInstance().broadcastChange(ContentManager.CONTENT_SHOW_LIST_PROGRESS, PROGRESS[progress++ % PROGRESS.length]);
}
private void fetchTitlesFromCollection() {
String response = fetchUrl(getHomeUrl(), CACHE_EXPIRY);
JSONObject data = parseJSON(response);
List<EpisodeBaseModel> titles = getEpisodesFromData(data, true);
for (EpisodeBaseModel ep : titles) {
episodes.put(ep.getHref(), ep);
}
}
private void fetchTitlesFromIndex() {
String response = fetchUrl(getIndexUrl(), CACHE_EXPIRY);
JSONObject data = parseJSON(response);
List<EpisodeBaseModel> titles = getEpisodesFromData(data, false);
Log.d(TAG, "Found " + titles.size() + " episode from index query");
for (EpisodeBaseModel title : titles) {
if (episodes.containsKey(title.getHref())) {
title.setCategories(episodes.get(title.getHref()).getCategories());
} else {
episodes.put(title.getHref(), title);
}
shows.add(title);
}
}
private void fetchTitlesInCategory(String cat) {
String response = fetchUrl(getCategoryUrl(cat), CACHE_EXPIRY);
JSONObject data = parseJSON(response);
List<EpisodeBaseModel> titles = getEpisodesFromData(data, false);
for (EpisodeBaseModel title : titles) {
if (episodes.containsKey(title.getHref())) {
title = episodes.get(title.getHref());
}
title.addCategory(cat);
episodes.put(title.getHref(), title);
}
}
private List<EpisodeBaseModel> getEpisodesFromData(JSONObject data, boolean addToCollection) {
List<EpisodeBaseModel> titles = new ArrayList<>();
if (data != null) {
Iterator<String> keys = data.keys();
while (keys.hasNext()) {
String key = keys.next();
try {
if (data.get(key) instanceof JSONArray) {
JSONArray groups = data.getJSONArray(key);
titles.addAll(getEpisodesFromList(groups, addToCollection));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
return titles;
}
private List<EpisodeBaseModel> getEpisodesFromList(JSONArray groups, boolean addToCollection) {
List<EpisodeBaseModel> titles = new ArrayList<>();
for (int i = 0, k = groups.length(); i < k; i++) {
try {
if (groups.get(i) instanceof JSONObject) {
JSONObject group = groups.getJSONObject(i);
List<EpisodeBaseModel> episodes = new ArrayList<>();
if (group.has("episodes") && group.get("episodes") instanceof JSONArray) {
JSONArray data = group.getJSONArray("episodes");
for (int j = 0, m = data.length(); j < m; j++) {
episodes.add(EpisodeModel.create(data.getJSONObject(j)));
}
}
if (episodes.size() > 0 && addToCollection && group.has("title") && group.get("title") instanceof String) {
collections.put(group.getString("title"), episodes);
}
titles.addAll(episodes);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
return titles;
}
private Uri getCategoryUrl(String cat) {
return buildApiUrl("category/" + cat);
}
private Uri getIndexUrl() {
String fields[] = {"seriesTitle", "href", "format", "formatBgColour", "formatTextColour", "channel", "pubDate", "thumbnail",
"livestream", "episodeHouseNumber", "categories", "title", "duration", "label", "rating", "episodeCount"};
Map<String, String> params = ImmutableMap.of("fields", TextUtils.join(",", fields));
return buildApiUrl("index", params);
}
private Uri getHomeUrl() {
String fields[] = {"seriesTitle", "href", "format", "formatBgColour", "formatTextColour", "channel", "pubDate", "thumbnail",
"livestream", "episodeHouseNumber", "categories", "title", "duration", "label", "rating"};
Map<String, String> params = ImmutableMap.of("fields", TextUtils.join(",", fields));
return buildApiUrl("home", params);
}
protected void onPreExecute() {
ContentManager.getInstance().broadcastChange(ContentManager.CONTENT_SHOW_LIST_START);
}
protected void onPostExecute(Void v) {
if (success) {
ContentManager.getInstance().broadcastChange(ContentManager.CONTENT_SHOW_LIST_DONE);
} else {
ContentManager.getInstance().broadcastChange(ContentManager.CONTENT_SHOW_LIST_ERROR);
}
episodes.clear();
shows.clear();
collections.clear();
}
}