package yuku.alkitab.base.ac;
import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
import android.text.Layout;
import android.text.SpannableStringBuilder;
import android.text.method.LinkMovementMethod;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.ViewFlipper;
import com.afollestad.materialdialogs.MaterialDialog;
import yuku.afw.V;
import yuku.afw.storage.Preferences;
import yuku.alkitab.base.App;
import yuku.alkitab.base.S;
import yuku.alkitab.base.U;
import yuku.alkitab.base.ac.base.BaseActivity;
import yuku.alkitab.base.dialog.VersesDialog;
import yuku.alkitab.base.widget.CallbackSpan;
import yuku.alkitab.debug.R;
import yuku.alkitab.model.Marker;
import yuku.alkitab.util.IntArrayList;
import yuku.alkitabconverter.util.DesktopVerseFinder;
import yuku.alkitabconverter.util.DesktopVerseParser;
import yuku.alkitabintegration.display.Launcher;
import java.util.Date;
public class NoteActivity extends BaseActivity {
//region static constructors
private static final String EXTRA_marker_id = "marker_id";
private static final String EXTRA_reference = "reference";
private static final String EXTRA_ariForNewNote = "ariForNewNote";
private static final String EXTRA_verseCountForNewNote = "verseCountForNewNote";
private static Intent createIntent(final long marker_id, final String reference, final int ariForNewNote, final int verseCountForNewNote) {
final Intent res = new Intent(App.context, NoteActivity.class);
res.putExtra(EXTRA_marker_id, marker_id);
res.putExtra(EXTRA_reference, reference);
res.putExtra(EXTRA_ariForNewNote, ariForNewNote);
res.putExtra(EXTRA_verseCountForNewNote, verseCountForNewNote);
return res;
}
/**
* Open the note edit dialog, editing existing note.
*/
public static Intent createEditExistingIntent(long _id) {
return createIntent(_id, null, 0, 0);
}
/**
* Open the note edit dialog for a new note by ari.
*/
public static Intent createNewNoteIntent(String reference, int ari, int verseCount) {
return createIntent(0, reference, ari, verseCount);
}
//endregion
Marker marker;
int ariForNewNote;
int verseCountForNewNote;
boolean editingMode;
boolean justClickedLink;
ViewFlipper viewFlipper;
TextView tCaptionReadOnly;
EditText tCaption;
int clickedTextOffset = -1;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_note);
final long _id = getIntent().getLongExtra(EXTRA_marker_id, 0L);
if (_id != 0L) {
marker = S.getDb().getMarkerById(_id);
}
String reference = getIntent().getStringExtra(EXTRA_reference);
ariForNewNote = getIntent().getIntExtra(EXTRA_ariForNewNote, 0);
verseCountForNewNote = getIntent().getIntExtra(EXTRA_verseCountForNewNote, 0);
if (reference == null) {
reference = S.activeVersion.referenceWithVerseCount(marker.ari, marker.verseCount);
}
setTitle(reference);
viewFlipper = V.get(this, R.id.viewFlipper);
tCaptionReadOnly = V.get(this, R.id.tCaptionReadOnly);
tCaption = V.get(this, R.id.tCaption);
final Toolbar toolbar = V.get(this, R.id.toolbar);
setSupportActionBar(toolbar);
final ActionBar ab = getSupportActionBar();
assert ab != null;
ab.setDisplayHomeAsUpEnabled(true);
if (marker != null) {
tCaptionReadOnly.setText(marker.caption);
tCaption.setText(marker.caption);
// editing existing note. Make the note read-only at first.
setEditingMode(false);
} else {
// a new note
setEditingMode(true);
}
}
@Override protected void onStart() {
super.onStart();
{ // apply background color, by overriding window background
getWindow().setBackgroundDrawable(new ColorDrawable(S.applied.backgroundColor));
}
// text formats
for (final TextView tv: new TextView[]{tCaption, tCaptionReadOnly}) {
tv.setTextColor(S.applied.fontColor);
tv.setTypeface(S.applied.fontFace, S.applied.fontBold);
tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, S.applied.fontSize2dp);
tv.setLineSpacing(0, S.applied.lineSpacingMult);
SettingsActivity.setPaddingBasedOnPreferences(tv);
}
getWindow().getDecorView().setKeepScreenOn(Preferences.getBoolean(getString(R.string.pref_keepScreenOn_key), getResources().getBoolean(R.bool.pref_keepScreenOn_default)));
}
static class VerseSpan extends CallbackSpan<String> {
VerseSpan(final String verse, final OnClickListener<String> verseClickListener) {
super(verse, verseClickListener);
}
}
final CallbackSpan.OnClickListener<String> verseClickListener = (widget, verse) -> {
justClickedLink = true;
final IntArrayList verseRanges = DesktopVerseParser.verseStringToAri(verse);
if (verseRanges == null || verseRanges.size() == 0) {
new MaterialDialog.Builder(widget.getContext())
.content(R.string.note_activity_cannot_parse_verse)
.positiveText(R.string.ok)
.show();
return;
}
final VersesDialog versesDialog = VersesDialog.newInstance(verseRanges);
versesDialog.setListener(new VersesDialog.VersesDialogListener() {
@Override
public void onVerseSelected(final VersesDialog dialog, final int ari) {
startActivity(Launcher.openAppAtBibleLocationWithVerseSelected(ari));
versesDialog.dismiss();
}
});
versesDialog.show(getSupportFragmentManager(), "dialog_verses");
};
void setEditingMode(final boolean editingMode) {
if (editingMode) {
viewFlipper.setDisplayedChild(1);
if (clickedTextOffset != -1) {
tCaption.setSelection(clickedTextOffset);
}
} else {
viewFlipper.setDisplayedChild(0);
// put verse links
final SpannableStringBuilder text = new SpannableStringBuilder(tCaptionReadOnly.getText());
DesktopVerseFinder.findInText(text, new DesktopVerseFinder.DetectorListener() {
@Override
public boolean onVerseDetected(final int start, final int end, final String verse) {
text.setSpan(new VerseSpan(verse, verseClickListener), start, end, 0);
return true;
}
@Override
public void onNoMoreDetected() {
}
});
tCaptionReadOnly.setText(text);
tCaptionReadOnly.setMovementMethod(LinkMovementMethod.getInstance());
tCaptionReadOnly.setOnTouchListener((v, event) -> {
// needed to calculate where the click is on the text layout
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
clickedTextOffset = -1;
final Layout layout = tCaptionReadOnly.getLayout();
if (layout != null) {
final int line = layout.getLineForVertical((int) event.getY() - tCaptionReadOnly.getTotalPaddingTop());
clickedTextOffset = layout.getOffsetForHorizontal(line, (int) event.getX() - tCaptionReadOnly.getTotalPaddingLeft());
}
}
return false;
});
tCaptionReadOnly.setOnClickListener(v -> {
if (!Preferences.getBoolean(R.string.pref_tapToEditNote_key, R.bool.pref_tapToEditNote_default)) {
return;
}
if (!justClickedLink) {
setEditingMode(true);
} else {
justClickedLink = false;
}
});
}
this.editingMode = editingMode;
invalidateOptionsMenu();
}
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.activity_note, menu);
return true;
}
@Override
public boolean onPrepareOptionsMenu(final Menu menu) {
final MenuItem menuEdit = menu.findItem(R.id.menuEdit);
final MenuItem menuDelete = menu.findItem(R.id.menuDelete);
final MenuItem menuOk = menu.findItem(R.id.menuOk);
menuEdit.setVisible(!editingMode);
menuDelete.setVisible(editingMode);
menuOk.setVisible(editingMode);
return true;
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case R.id.menuEdit: {
setEditingMode(true);
}
return true;
case R.id.menuDelete: {
// if it's indeed not exist, check if we have some text, if we do, prompt first
if (marker != null || tCaption.length() > 0) {
new MaterialDialog.Builder(this)
.content(R.string.anda_yakin_mau_menghapus_catatan_ini)
.positiveText(R.string.delete)
.onPositive((dialog, which) -> {
if (marker != null) {
// really delete from db
S.getDb().deleteNonBookmarkMarkerById(marker._id);
} else {
// do nothing, because it's indeed not in the db, only in editor buffer
}
setResult(RESULT_OK);
realFinish();
})
.negativeText(R.string.cancel)
.show();
} else { // no existing marker and buffer is empty
realFinish(); // no need to setResult(RESULT_OK), because nothing is to be reloaded
}
}
return true;
case R.id.menuOk: {
ok_click();
}
return true;
}
return super.onOptionsItemSelected(item);
}
void ok_click() {
if (editingMode) { // if we are not editing, do not bother checking and saving.
final String caption = tCaption.getText().toString();
final Date now = new Date();
if (marker != null) { // update existing marker
if (U.equals(marker.caption, caption)) {
// when there is no change, do nothing
} else {
if (caption.length() == 0) { // delete instead of update
S.getDb().deleteNonBookmarkMarkerById(marker._id);
} else {
marker.caption = caption;
marker.modifyTime = now;
S.getDb().insertOrUpdateMarker(marker);
}
}
} else { // marker == null; not existing, so only insert when there is some text
if (caption.length() > 0) {
marker = S.getDb().insertMarker(ariForNewNote, Marker.Kind.note, caption, verseCountForNewNote, now, now);
}
}
setResult(RESULT_OK);
}
realFinish();
}
@Override
public void finish() {
// make sure we save it before exiting this screen
ok_click();
realFinish();
}
void realFinish() {
super.finish();
}
}