package com.airlocksoftware.hackernews.loader;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.v4.content.AsyncTaskLoader;
import android.util.Log;
import com.airlocksoftware.hackernews.cache.DbHelperSingleton;
import com.airlocksoftware.hackernews.model.*;
import com.airlocksoftware.hackernews.parser.StoryParser;
import com.airlocksoftware.hackernews.parser.StoryParser.StoryResponse;
import com.crashlytics.android.Crashlytics;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
public class StoryLoader extends AsyncTaskLoader<StoryResponse> {
private Page mPage;
private Request mRequest;
private String mUsername;
// private String mMoreFnid;
private StoryResponse mResponse;
private boolean mResultsToDeliver = false;
// Constants
private static final String TAG = StoryLoader.class.getSimpleName();
private static final String SUBMISSIONS_TIMESTAMP_ID = "Submissions";
private static final String PAGE_TIMESTAMP_ID = "Page";
/** Parse stories from Front Page, Ask, Best, or New **/
public StoryLoader(Context context, Page page, Request request) {
super(context);
mPage = page;
mRequest = request;
mUsername = null;
setCrashlyticsKeys();
}
/** Parse stories from the user's submissions page **/
public StoryLoader(Context context, String username, Request request) {
super(context);
mPage = null;
mRequest = request;
mUsername = username;
setCrashlyticsKeys();
}
private void setCrashlyticsKeys() {
String pageString = (mPage != null) ? mPage.toString() : null;
boolean usernameBlank = (mRequest == null || StringUtils.isBlank(mUsername));
boolean reqEmpty = (mRequest == null || mRequest.isEmpty());
Crashlytics.setString("StoryLoader :: mPage", pageString);
Crashlytics.setBool("StoryLoader :: mUsernameBlank?", usernameBlank);
Crashlytics.setBool("StoryLoader :: mRequestEmpty?", reqEmpty);
}
@Override
public StoryResponse loadInBackground() {
StoryResponse response = StoryResponse.NULL_RESPONSE;
if (mUsername != null) response = loadSubmissions(mUsername, mRequest);
else if (mPage != null) response = loadStories(mPage, mRequest);
return response;
}
/** Loads the requested page of stories, either from news.ycombinator.com or from the cache. **/
private StoryResponse loadStories(Page page, Request request) {
SQLiteDatabase db = DbHelperSingleton.getInstance(getContext()).getWritableDatabase();
StoryResponse response = null;
// handle cache
StoryTimestamp timestamp = StoryTimestamp.cachedByBothIds(db, PAGE_TIMESTAMP_ID, page.toString());
if (timestamp != null && request == Request.NEW) {
List<Story> stories = Story.cachedByPage(db, page);
if (stories.size() > 0) {
response = new StoryResponse();
response.stories = stories;
response.result = Result.SUCCESS;
response.timestamp = timestamp;
}
}
// no hit in the cache or it's a MORE or REFRESH request
if (response == null) {
String moreFnid = null;
if (request == Request.MORE && timestamp != null) moreFnid = timestamp.fnid;
response = StoryParser.parseStoryList(getContext(), page, request, moreFnid);
switch (response.result) {
case SUCCESS:
Story.clearCache(db, page);
Story.cacheValues(db, response.stories);
break;
case MORE:
Story.cacheValues(db, response.stories);
break;
case FAILURE:
if (moreFnid != null) response.result = Result.FNID_EXPIRED;
default:
break;
}
// need to cache new moreFnid
if (response.timestamp != null) {
// delete old one
if (timestamp != null) timestamp.delete(db);
// create new one
response.timestamp.primaryId = PAGE_TIMESTAMP_ID;
response.timestamp.secondaryId = page.toString();
response.timestamp.create(db);
Log.d(TAG, "new Story FNID = " + response.timestamp.fnid);
}
}
mResultsToDeliver = true;
mResponse = response;
return response;
}
/** Loads StoryResposne from a user's submissions page, and caches the moreFnid (if any) in the timestamp db. **/
private StoryResponse loadSubmissions(String username, Request request) {
SQLiteDatabase db = DbHelperSingleton.getInstance(getContext())
.getWritableDatabase();
StoryResponse response = null;
// check for more
StoryTimestamp timestamp = StoryTimestamp.cachedByPrimaryId(db, SUBMISSIONS_TIMESTAMP_ID);
if (request == Request.MORE && timestamp != null && timestamp.secondaryId.equals(username)) {
response = StoryParser.parseUserSubmissions(getContext(), username, timestamp.fnid);
}
// either this is a new request or we have no moreFnid
if (response == null) {
response = StoryParser.parseUserSubmissions(getContext(), username, null);
}
// delete the old one if it exists
if (timestamp != null) timestamp.delete(db);
// need to cache new moreFnid (if any)
if (response.timestamp != null) {
response.timestamp.primaryId = SUBMISSIONS_TIMESTAMP_ID;
response.timestamp.secondaryId = username;
response.timestamp.create(db);
}
mResultsToDeliver = true;
mResponse = response;
return response;
}
/**
* Handles a request to start the Loader.
*/
@Override
protected void onStartLoading() {
if (mResponse != null && mResultsToDeliver) {
deliverResult(mResponse);
} else {
forceLoad();
}
}
@Override
public void deliverResult(StoryResponse response) {
mResultsToDeliver = false;
super.deliverResult(response);
}
}