package org.theotech.ceaselessandroid.scripture; import android.app.Activity; import android.os.AsyncTask; import android.util.Log; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Locale; /** * Created by Ben Johnson on 10/3/15. */ public class ScriptureServiceImpl implements ScriptureService { private static final String TAG = "ScriptureServiceImpl"; private static final String HTTP_API_VOTD = "http://api.ceaselessprayer.com/v1/votd"; private static final String HTTP_API_GET_SCRIPTURE = "http://api.ceaselessprayer.com/v1/getScripture"; private static final Integer SCRIPTURE_CACHE_SIZE = 5; private static final String SCRIPTURE_CACHE_FILE = "scriptureCacheFile"; private static ScriptureService instance; protected Activity activity; private List<ScriptureData> cachedScriptures; public static ScriptureService getInstance(Activity activity) { if (instance == null) { instance = new ScriptureServiceImpl(activity); } return instance; } public ScriptureServiceImpl(Activity activity) { this.activity = activity; this.cachedScriptures = loadCacheFromFile(); } @Override public ScriptureData getScripture() { return popScripture(); } protected ScriptureData popScripture() { ScriptureData result = null; if (cachedScriptures.size() > 0) { result = cachedScriptures.remove(0); } new ScriptureCacher().execute(); return result; } protected synchronized void fillScriptureCache() { while (cachedScriptures.size() < SCRIPTURE_CACHE_SIZE) { cachedScriptures.add(loadNewScripture()); } writeCacheToFile(); } private void writeCacheToFile() { ObjectOutputStream oos = null; try { File scriptureCacheFile = new File(activity.getCacheDir(), SCRIPTURE_CACHE_FILE); FileOutputStream fout = new FileOutputStream(scriptureCacheFile); oos = new ObjectOutputStream(fout); oos.writeObject(cachedScriptures); oos.close(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (oos != null) { oos.close(); } } catch (IOException e) { e.printStackTrace(); } } } private List<ScriptureData> loadCacheFromFile() { File scriptureCacheFile = new File(activity.getCacheDir(), SCRIPTURE_CACHE_FILE); if (scriptureCacheFile.exists()) { Log.d(TAG, "Loading scripture cache file"); ObjectInputStream ois = null; try { FileInputStream fin = new FileInputStream(scriptureCacheFile); ois = new ObjectInputStream(fin); List<ScriptureData> scriptureCache = (List<ScriptureData>) ois.readObject(); ois.close(); return scriptureCache; } catch (Exception e) { e.printStackTrace(); } finally { try { if (ois != null) { ois.close(); } } catch (IOException e) { e.printStackTrace(); } } } // default to empty list if we fail to load the file return new ArrayList<>(); } protected ScriptureData loadNewScripture() { ScriptureReference ref = getVerseReference(); ScriptureData data = null; if (ref != null) { data = getScriptureData(ref); } return data; } protected ScriptureReference getVerseReference() { // HTTP Get InputStream in; try { URL url = new URL(HTTP_API_VOTD + "?language=" + Locale.getDefault().toString()); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); in = new BufferedInputStream(urlConnection.getInputStream()); } catch (Exception e) { Log.e(TAG, Log.getStackTraceString(e)); return null; } String json = null; BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(in)); StringBuilder sb = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { sb.append(line); } json = sb.toString(); } catch (IOException e) { Log.e(TAG, Log.getStackTraceString(e)); return null; } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { Log.w(TAG, Log.getStackTraceString(e)); } } } // parse JSON response ScriptureReference ref; try { Log.d(TAG, "json = " + json); JSONObject obj = new JSONObject(json); String book = obj.getString("book"); String chapter = obj.getString("chapter"); String verse_start = obj.getString("verse_start"); String verse_end = obj.getString("verse_end"); ref = new ScriptureReference(book, chapter, verse_start, verse_end, obj.toString()); } catch (JSONException e) { Log.e(TAG, Log.getStackTraceString(e)); return null; } return ref; } private ScriptureData getScriptureData(ScriptureReference ref) { // HTTP Post InputStream in; try { JSONObject json = new JSONObject(ref.getJson()); json.put("language", Locale.getDefault().toString()); Log.d(TAG, json.toString()); byte[] postDataBytes = json.toString().getBytes("UTF-8"); URL url = new URL(HTTP_API_GET_SCRIPTURE); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setInstanceFollowRedirects(false); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/json"); conn.setRequestProperty("charset", "utf-8"); conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); conn.setUseCaches(false); conn.getOutputStream().write(postDataBytes); in = new BufferedInputStream(conn.getInputStream()); } catch (Exception e) { Log.e(TAG, Log.getStackTraceString(e)); return null; } String json = null; BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(in)); StringBuilder sb = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { sb.append(line); } json = sb.toString(); } catch (IOException e) { Log.e(TAG, Log.getStackTraceString(e)); return null; } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { Log.w(TAG, Log.getStackTraceString(e)); } } } // Parse JSON response ScriptureData data; try { JSONObject obj = new JSONObject(json); String text = obj.getString("text"); String citation = obj.getString("citation"); String bible = obj.getString("bible"); JSONObject refObj = new JSONObject(ref.getJson()); String link = String.format("%s/%s/%s/%s#%s", "http://www.bible.is", bible, refObj.getString("book"), refObj.getString("chapter"), refObj.getString("verse_start")); Log.d(TAG, link); data = new ScriptureData(text, citation, link, json); } catch (JSONException e) { Log.e(TAG, Log.getStackTraceString(e)); return null; } return data; } private class ScriptureCacher extends AsyncTask<String, Void, Void> { @Override protected Void doInBackground(String... params) { fillScriptureCache(); return null; } } }