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();
        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_ERROR);
        }
        episodes.clear();
        shows.clear();
        collections.clear();
    }
}

@@ -2551,32 +2551,60 @@
 dateProgress();%0A
+        Log.d(TAG, %22DONE%22);%0A
         success 
@@ -7403,17 +7403,16 @@
     if (
-!
 success)
@@ -7410,24 +7410,138 @@
 (success) %7B%0A
+            ContentManager.getInstance().broadcastChange(ContentManager.CONTENT_SHOW_LIST_DONE);%0A        %7D else %7B%0A
             

Fix missing DONE broadcast in iview