package net.bible.android.control.page;
import android.app.Activity;
import android.util.Log;
import net.bible.android.control.versification.BibleTraverser;
import net.bible.android.view.activity.navigation.GridChoosePassageBook;
import net.bible.service.common.CommonUtils;
import net.bible.service.sword.SwordContentFacade;
import net.bible.service.sword.SwordDocumentFacade;
import org.apache.commons.lang3.StringUtils;
import org.crosswire.jsword.book.Book;
import org.crosswire.jsword.book.BookCategory;
import org.crosswire.jsword.passage.Key;
import org.crosswire.jsword.passage.KeyUtil;
import org.crosswire.jsword.passage.NoSuchKeyException;
import org.crosswire.jsword.passage.Verse;
import org.crosswire.jsword.versification.BibleBook;
import org.crosswire.jsword.versification.Versification;
import org.json.JSONException;
import org.json.JSONObject;
/** Reference to current passage shown by viewer
*
* @author Martin Denham [mjdenham at gmail dot com]
* @see gnu.lgpl.License for license details.<br>
* The copyright to this program is held by it's author.
*/
public class CurrentBiblePage extends VersePage implements CurrentPage {
private static final String TAG = "CurrentBiblePage";
/* default */ CurrentBiblePage(CurrentBibleVerse currentBibleVerse, BibleTraverser bibleTraverser, SwordContentFacade swordContentFacade, SwordDocumentFacade swordDocumentFacade) {
super(true, currentBibleVerse, bibleTraverser, swordContentFacade, swordDocumentFacade);
}
public BookCategory getBookCategory() {
return BookCategory.BIBLE;
}
public Class<? extends Activity> getKeyChooserActivity() {
return GridChoosePassageBook.class;
}
/* (non-Javadoc)
* @see net.bible.android.control.CurrentPage#next()
*/
@Override
public void next() {
Log.d(TAG, "Next");
nextChapter();
}
/* go to prev verse quietly without updates
*/
public void doPreviousVerse() {
Log.d(TAG, "Previous verse");
Versification versification = getVersification();
Verse verse = getCurrentBibleVerse().getVerseSelected(versification);
getCurrentBibleVerse().setVerseSelected(versification, getBibleTraverser().getPrevVerse(getCurrentPassageBook(), verse));
}
/* go to next verse quietly without updates
*/
public void doNextVerse() {
Log.d(TAG, "Next verse");
Versification versification = getVersification();
Verse verse = getCurrentBibleVerse().getVerseSelected(versification);
getCurrentBibleVerse().setVerseSelected(versification, getBibleTraverser().getNextVerse(getCurrentPassageBook(), verse));
}
/* (non-Javadoc)
* @see net.bible.android.control.CurrentPage#previous()
*/
@Override
public void previous() {
Log.d(TAG, "Previous");
previousChapter();
}
private void nextChapter() {
setKey( getKeyPlus(+1) );
}
private void previousChapter() {
setKey( getKeyPlus(-1) );
}
/** add or subtract a number of pages from the current position and return Verse
*/
public Verse getKeyPlus(int num) {
Verse currVer = this.getCurrentBibleVerse().getVerseSelected(getVersification());
try {
Verse nextVer = currVer;
if (num>=0) {
// move to next book if required
for (int i=0; i<num; i++) {
nextVer = getBibleTraverser().getNextChapter(getCurrentPassageBook(), nextVer);
}
} else {
// move to prev book if required
// allow standard loop structure by changing num to positive
num = -num;
for (int i=0; i<num; i++) {
nextVer = getBibleTraverser().getPrevChapter(getCurrentPassageBook(), nextVer);
}
}
return nextVer;
} catch (Exception nsve) {
Log.e(TAG, "Incorrect verse", nsve);
return currVer;
}
}
/** add or subtract a number of pages from the current position and return Page
*/
public Key getPagePlus(int num) {
Verse targetChapterVerse1 = getKeyPlus(num);
// convert to full chapter before returning because bible view is for a full chapter
return CommonUtils.getWholeChapter(targetChapterVerse1);
}
/* (non-Javadoc)
* @see net.bible.android.control.CurrentPage#setKey(java.lang.String)
*/
public void setKey(String keyText) {
Log.d(TAG, "key text:"+keyText);
try {
Key key = getCurrentDocument().getKey(keyText);
setKey(key);
} catch (NoSuchKeyException nske) {
Log.e(TAG, "Invalid verse reference:"+keyText);
}
}
/** set key without notification
*
* @param key
*/
public void doSetKey(Key key) {
if (key!=null) {
Verse verse = KeyUtil.getVerse(key);
//TODO av11n should this be the verse Versification or the Module/doc's Versification
getCurrentBibleVerse().setVerseSelected(getVersification(), verse);
}
}
/* (non-Javadoc)
* @see net.bible.android.control.CurrentPage#getSingleKey()
*/
@Override
public Verse getSingleKey() {
Key key = doGetKey(true);
// it is already a Verse but this avoids a downcast
return KeyUtil.getVerse(key);
}
/* (non-Javadoc)
* @see net.bible.android.control.CurrentPage#getKey()
*/
@Override
public Key getKey() {
return doGetKey(false);
}
private Key doGetKey(boolean requireSingleKey) {
Verse verse = getCurrentBibleVerse().getVerseSelected(getVersification());
if (verse!=null) {
Key key;
if (!requireSingleKey) {
// display whole page of bible so return whole chapter key - not just the single verse even if a single verse was set in verseKey
// if verseNo is required too then use getVerseRange()
key = CommonUtils.getWholeChapter(verse);
} else {
key = verse;
}
return key;
} else {
Log.w(TAG, "No verse, returning default verse Gen 1.1");
return new Verse(getVersification(), BibleBook.GEN,1,1, true);
}
}
@Override
public boolean isSingleKey() {
return false;
}
public int getCurrentVerseNo() {
return getCurrentBibleVerse().getVerseNo();
}
public void setCurrentVerseNo(int verse) {
getCurrentBibleVerse().setVerseNo(verse);
onVerseChange();
}
/** called during app close down to save state
*/
@Override
public JSONObject getStateJson() throws JSONException {
JSONObject object = new JSONObject();
if (getCurrentDocument()!=null && getCurrentBibleVerse()!=null && getCurrentBibleVerse().getVerseSelected(getVersification())!=null) {
Log.d(TAG, "Saving Bible state for 1 window");
object.put("document", getCurrentDocument().getInitials());
object.put("verse", getCurrentBibleVerse().getStateJson());
}
return object;
}
/** called during app start-up to restore previous state
*/
@Override
public void restoreState(JSONObject jsonObject) throws JSONException {
if (jsonObject!=null) {
Log.d(TAG, "Restoring Bible page state");
if (jsonObject.has("document")) {
String document = jsonObject.getString("document");
if (StringUtils.isNotEmpty(document)) {
Log.d(TAG, "State document:"+document);
Book book = getSwordDocumentFacade().getDocumentByInitials(document);
if (book!=null) {
Log.d(TAG, "Restored document:"+book.getName());
// bypass setter to avoid automatic notifications
localSetCurrentDocument(book);
getCurrentBibleVerse().restoreState(jsonObject.getJSONObject("verse"));
}
}
}
}
}
/** can we enable the main menu search button
*/
@Override
public boolean isSearchable() {
try {
//TODO allow japanese search - japanese bibles use smartcn which is not available
return !"ja".equals(getCurrentDocument().getLanguage().getCode());
} catch (Exception e) {
Log.w(TAG, "Missing language code", e);
return true;
}
}
}