package yuku.alkitab.base.dialog;
import android.content.Context;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.text.SpannableStringBuilder;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.StyleSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.afollestad.materialdialogs.MaterialDialog;
import yuku.afw.D;
import yuku.afw.V;
import yuku.alkitab.base.S;
import yuku.alkitab.base.dialog.base.BaseDialog;
import yuku.alkitab.base.util.Appearances;
import yuku.alkitab.base.util.TargetDecoder;
import yuku.alkitab.base.widget.VerseRenderer;
import yuku.alkitab.base.widget.VersesView;
import yuku.alkitab.base.widget.VersesView.VerseSelectionMode;
import yuku.alkitab.debug.R;
import yuku.alkitab.model.SingleChapterVerses;
import yuku.alkitab.model.Version;
import yuku.alkitab.model.XrefEntry;
import yuku.alkitab.util.Ari;
import yuku.alkitab.util.IntArrayList;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class XrefDialog extends BaseDialog {
public static final String TAG = XrefDialog.class.getSimpleName();
private static final String EXTRA_arif = "arif";
public interface XrefDialogListener {
void onVerseSelected(XrefDialog dialog, int arif_source, int ari_target);
}
TextView tXrefText;
VersesView versesView;
XrefDialogListener listener;
int arif_source;
XrefEntry xrefEntry;
int displayedLinkPos = -1; // -1 indicates that we should auto-select the first link
List<String> displayedVerseTexts;
List<String> displayedVerseNumberTexts;
IntArrayList displayedRealAris;
Version sourceVersion = S.activeVersion;
String sourceVersionId = S.activeVersionId;
float textSizeMult = S.getDb().getPerVersionSettings(sourceVersionId).fontSizeMultiplier;
public XrefDialog() {
}
public static XrefDialog newInstance(int arif) {
XrefDialog res = new XrefDialog();
Bundle args = new Bundle();
args.putInt(EXTRA_arif, arif);
res.setArguments(args);
return res;
}
@Override
public void onAttach(final Context context) {
super.onAttach(context);
if (getParentFragment() instanceof XrefDialogListener) {
listener = (XrefDialogListener) getParentFragment();
} else {
listener = (XrefDialogListener) context;
}
}
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_TITLE, 0);
arif_source = getArguments().getInt(EXTRA_arif);
xrefEntry = sourceVersion.getXrefEntry(arif_source);
}
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View res = inflater.inflate(R.layout.dialog_xref, container, false);
tXrefText = V.get(res, R.id.tXrefText);
versesView = V.get(res, R.id.versesView);
res.setBackgroundColor(S.applied.backgroundColor);
versesView.setCacheColorHint(S.applied.backgroundColor);
versesView.setVerseSelectionMode(VerseSelectionMode.singleClick);
versesView.setSelectedVersesListener(versesView_selectedVerses);
tXrefText.setMovementMethod(LinkMovementMethod.getInstance());
if (xrefEntry != null) {
renderXrefText();
} else {
new MaterialDialog.Builder(getActivity())
.content(String.format(Locale.US, "Error: xref at arif 0x%08x couldn't be loaded", arif_source))
.positiveText(R.string.ok)
.show();
}
return res;
}
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (xrefEntry == null) {
dismiss();
}
}
void renderXrefText() {
final SpannableStringBuilder sb = new SpannableStringBuilder();
sb.append(VerseRenderer.XREF_MARK);
sb.append(" ");
final int[] linkPos = {0};
findTags(xrefEntry.content, new FindTagsListener() {
@Override public void onTaggedText(final String tag, int start, int end) {
final int thisLinkPos = linkPos[0];
linkPos[0]++;
int sb_len = sb.length();
sb.append(xrefEntry.content, start, end);
if (tag.startsWith("t")) { // the only supported tag at the moment
final String encodedTarget = tag.substring(1);
if (thisLinkPos == displayedLinkPos || (displayedLinkPos == -1 && thisLinkPos == 0)) {
// just make it bold, because this is the currently displayed link
sb.setSpan(new StyleSpan(Typeface.BOLD), sb_len, sb.length(), 0);
if (displayedLinkPos == -1) {
showVerses(0, encodedTarget);
}
} else {
sb.setSpan(new ClickableSpan() {
@Override public void onClick(View widget) {
showVerses(thisLinkPos, encodedTarget);
}
}, sb_len, sb.length(), 0);
}
}
}
@Override public void onPlainText(int start, int end) {
sb.append(xrefEntry.content, start, end);
}
});
Appearances.applyTextAppearance(tXrefText, textSizeMult);
tXrefText.setText(sb);
}
void showVerses(int linkPos, String encodedTarget) {
displayedLinkPos = linkPos;
final IntArrayList ranges = decodeTarget(encodedTarget);
if (D.EBUG) {
Log.d(TAG, "linkPos " + linkPos + " target=" + encodedTarget + " ranges=" + ranges);
}
displayedVerseTexts = new ArrayList<>();
displayedVerseNumberTexts = new ArrayList<>();
displayedRealAris = new IntArrayList();
int verse_count = sourceVersion.loadVersesByAriRanges(ranges, displayedRealAris, displayedVerseTexts);
if (verse_count > 0) {
// set up verse number texts
for (int i = 0; i < verse_count; i++) {
int ari = displayedRealAris.get(i);
displayedVerseNumberTexts.add(Ari.toChapter(ari) + ":" + Ari.toVerse(ari));
}
class Verses extends SingleChapterVerses {
@Override public String getVerse(int verse_0) {
final String res = displayedVerseTexts.get(verse_0);
// prevent crash if the target xref is not available
if (res == null) {
return getString(R.string.generic_verse_not_available_in_this_version);
}
return res;
}
@Override public int getVerseCount() {
return displayedVerseTexts.size();
}
@Override public String getVerseNumberText(int verse_0) {
return displayedVerseNumberTexts.get(verse_0);
}
}
int firstAri = displayedRealAris.get(0);
versesView.setData(Ari.toBookChapter(firstAri), new Verses(), null, null, 0, sourceVersion, sourceVersionId);
}
renderXrefText();
}
private IntArrayList decodeTarget(final String encodedTarget) {
return TargetDecoder.decode(encodedTarget);
}
VersesView.SelectedVersesListener versesView_selectedVerses = new VersesView.DefaultSelectedVersesListener() {
@Override public void onVerseSingleClick(VersesView v, int verse_1) {
listener.onVerseSelected(XrefDialog.this, arif_source, displayedRealAris.get(verse_1 - 1));
}
};
interface FindTagsListener {
void onPlainText(int start, int end);
void onTaggedText(String tag, int start, int end);
}
// look for "<@" "@>" "@/" tags
void findTags(String s, FindTagsListener listener) {
int pos = 0;
while (true) {
int p = s.indexOf("@<", pos);
if (p == -1) break;
listener.onPlainText(pos, p);
int q = s.indexOf("@>", p+2);
if (q == -1) break;
int r = s.indexOf("@/", q+2);
if (r == -1) break;
listener.onTaggedText(s.substring(p+2, q), q+2, r);
pos = r+2;
}
listener.onPlainText(pos, s.length());
}
public void setSourceVersion(Version sourceVersion, String sourceVersionId) {
this.sourceVersion = sourceVersion;
this.sourceVersionId = sourceVersionId;
textSizeMult = S.getDb().getPerVersionSettings(sourceVersionId).fontSizeMultiplier;
}
}