
function showBibleLookup() {
  changePage("main-sub-page", null);
  $("title").text(tr("biblelookup.title", [ tr("appname") ]));

  var containerE = $("#main-sub-page");
  containerE.empty();
  uiSectionTitle({
    container: $("<div/>").appendTo(containerE),
    text : tr("mainpage.bible.hebrew"),
  });
  var $hebrew = $("<div id='hebrew' class='bible-books'/>").appendTo(containerE);
  uiSectionTitle({
    container: $("<div/>").appendTo(containerE),
    text : tr("mainpage.bible.greek"),
  });
  var $greek = $("<div id='greek' class='bible-books'/>").appendTo(containerE);

  var i = 0;
  var $row;
  BibleText.books.forEach(function(book) {
    if (book.num == 40) { // Matthew
      i = 0;
    }
    if (i % 6 == 0) {
      var $books = book.num < 40 ? $hebrew : $greek;
      $row = $("<div class='row' />").appendTo($books);
    }
    var $book = $("<span class='book' />").appendTo($row);
    $book.text(book.abbrTr);
    $book.attr("name", book.code);
    $book.attr("group", book.group);
    $book.click(cbParams(doBibleLookupChapter, book));
    i++;
  });
}

function doBibleLookupChapter(book) {
  var containerE = $("#main-sub-page");
  containerE.empty();
  uiSectionTitle({
    container: $("<div/>").appendTo(containerE),
    text : tr("mainpage.bible.chapter.title", book.longTr),
  });
  var $chapters = $("<div class='bible-chapters' />").appendTo(containerE);
  var $row;
  for (var i = 1; i <= book.chapterCount; i++) {
    if (i % 10 == 1) {
      $row = $("<div class='row'/>").appendTo($chapters);
    }
    var chE = $("<span class='chapterNum' />").appendTo($row);
    chE.text(i + "");
    var chapter = new BibleText(book.code + " " + i);
    chE.click(cbParams(showDetail, chapter));
  };
}



/**
 * Shows |BibleText| object
 *
 * Creates the UI for reading the Bible, displaying a full chapter.
 * Can highlight some verses, to show a reference.
 *
 * TODO: Show events, places and persons on the side
 * next to the relevant verse.
 *
 * Creates:
 * uiDescr
 * TODO:
 * uiList with sources (explaining or referencing this one)
 *
 * @param container {jquery DOM Element}   <div> where to add the UI
 * @param source {BibleText}   The text to display
 * @param navFunc {Function}
 *     Called when the user clicks on another object and it should be shown.
 * @param errorCallback {Function(e)}
 */
function uiBible(p) {
  assert(p.container, "div: need element");
  assert(p.source instanceof BibleText, "source: need");
  assert(typeof(p.navFunc) == "function", "navFunc: need function");
  p.container.addClass("detail");
  p.container.addClass("source");
  p.container.addClass("bible");

  // chapter forward/back etc.
  var $navButtons = $("<div id='bible-nav-buttons' class='button-list'/>").appendTo(p.container);
  if (p.source.range == 3 || p.source.range == 0) {
    var $chapterPrev = uiButton({
      $container : $navButtons,
      title : tr("page.biblereader.prev"),
      classes : "bible-prev",
      errorCallback : p.errorCallback,
      clickCallback : function() {
        var prev = p.source.range == 0 ? p.source.prevVerse() : p.source.prevChapter();
        p.navFunc(prev, null, null, { historyReplaceLast: true });
      },
    });
    var $chapterPrev = uiButton({
      $container : $navButtons,
      title : tr("page.biblereader.next"),
      classes : "bible-next",
      errorCallback : p.errorCallback,
      clickCallback : function() {
        var next = p.source.range == 0 ? p.source.nextVerse() : p.source.nextChapter();
        p.navFunc(next, null, null, { historyReplaceLast: true });
      },
    });
  }
  if (p.source.range != 3) {
    var chapterWholeE = uiButton({
      $container : $navButtons,
      title : tr("page.biblereader.context"),
      classes : "bible-chapter-whole",
      errorCallback : p.errorCallback,
      clickCallback : function() {
        p.navFunc(p.source.wholeChapter(true));
      },
    });
  }

  var $objects = $("<div class='objects'/>").appendTo(p.container);
  var refs = p.source.findAllReferencingObjects(gStorage, function(refs) {
    refs = refs.concat(p.source.relations.filter(function(rel) { return rel.obj; }));
    var events = refs.filter(function(obj) { return obj instanceof Event; });
    var persons = refs.filter(function(obj) { return obj instanceof Person; });
    var places = refs.filter(function(obj) { return obj instanceof Place; });
    var sources = refs.filter(function(obj) { return obj instanceof Source; });

    if (events.length > 0) {
      uiEventList({
        container : $objects,
        events : events,
        navFunc : p.navFunc,
      });
    }
    if (places.length > 0) {
      uiList({
        container : $objects,
        columns : [
          { label : tr("page.bible.place.th"), displayFunc : function(place) { return place.name; } },
        ],
        data : places,
        clickFunc : function(obj) { p.navFunc(obj, places, tr("page.bible.place.hl", p.source.name)); },
      });
    }
    if (persons.length > 0) {
      uiList({
        container : $objects,
        columns : [
          { label : tr("page.bible.persons.th"), displayFunc : function(person) { return person.name; } },
        ],
        data : persons,
        clickFunc : function(obj) { p.navFunc(obj, persons, tr("page.bible.persons.hl", p.source.name)); },
      });
    }
    if (sources.length > 0) {
      uiSourceList({
        container : p.container,
        events : sources,
        navFunc : p.navFunc,
      });
    }

    if (places.length > 5) {
      uiMap({
        container : p.container,
        events : events,
        places : places,
        obj : p.source,
        navFunc : p.navFunc,
        errorCallback : p.errorCallback,
      });
    }
  }, p.errorCallback);

  var descrE = $("<div/>").appendTo(p.container);
  p.source.load(function() {
    if (p.source.range != 3) { // single verse or range
      var $descr = uiDescr({
        container: descrE,
        text : p.source.quote,
      });
      enhanceDOMTextWithLinks({
        container : $descr,
        objs : p.source.allRelatedObjs,
        navFunc : p.navFunc,
        errorCallback : p.errorCallback,
      });
      showVerseExtras({
        bv : p.source,
        linkedObjs : p.linkedObjs,
        navFunc : p.navFunc,
        errorCallback : p.errorCallback,
        $container : p.container,
        inline : false,
      });
    } else { // whole chapter
      // Instead of using one long descr, we'll be iterating over the verses,
      // because we need that info later.
      descrE.addClass("descr");
      descrE.addClass("bible-reader");
      var hint = uiHint({
        msgID : "page.bible.clickversenum.hint",
        container : $("<div/>").insertBefore(descrE),
      });
      var $highlight = null;

      var maxVerse = p.source.book.maxVerse[p.source.chapter];
      for (var verse = 1; verse <= maxVerse; verse++) {
        var bv = p.source.clone();
        bv.verse = verse;
        bv.verseTo = 0;
        bv.init();
        var $verse = showVerse({
          bv : bv,
          linkedObjs : p.source.allRelatedObjs,
          $descr : descrE,
          navFunc : p.navFunc,
          errorCallback : p.errorCallback,
          hint : hint,
        });

        // highlight verse in chapter
        if (p.source.highlight && p.source.highlight.contains(bv)) {
          $verse.attr("highlight", "true");
          if ( !$highlight) {
            $highlight = $verse;
          }
        }
      }
      try {
        if ($highlight) {
          $highlight.get(0).scrollIntoView(true);
        }
      } catch (e) { errorNonCritical(e); }
    }
  }, p.errorCallback);
}

/**
 * @param bv {BibleText} with a single verse
 * @param linkedObjs {Array of Detail}  objects related to the verse
 * @param $descr {JQuery element}
 * @param navFunc {Function}
 * @returns {JQuery-Element}
 */
function showVerse(p) {
  var bv = p.bv;
  var verseE = $("<a class='verse'/>").appendTo(p.$descr)
      .attr("verse", bv.verse).prop("obj", bv);
  bv.load(function() {
    var verserMarkerE = $("<span class='verse-marker'/>").attr("verse", bv.verse).text(" " + bv.verse + " ").appendTo(verseE);
    var first = true;
    bv.quote.split("\n").forEach(function(line) {
      if (first) {
        first = false;
        $("<span class='verse'/>").text(line).appendTo(verseE);
      } else {
        $("<div class='verse descr-p'/>").text(line).appendTo(verseE);
      }
    });
    enhanceDOMTextWithLinks({
      container : verseE,
      objs : p.linkedObjs,
      navFunc : p.navFunc,
      errorCallback : p.errorCallback,
    });
    verserMarkerE.click(function() {
      try {
        p.navFunc(bv); // Go to verse page
        /* Alternatively: Show inline in chapter
        showVerseExtras({
          bv : bv,
          linkedObjs : p.linkedObjs,
          navFunc : p.navFunc,
          errorCallback : p.errorCallback,
          $container : verseE,
          inline : true,
        }); */
        if (p.hint) {
          p.hint.noMore();
          p.hint.close();
        }
      } catch (e) { p.errorCallback(e); }
    });
  }, p.errorCallback);
  return verseE;
}

/**
 * Shows a box that has additional information and commands for that verse.
 * That includes:
 * - All referencing objects in DB for that verse (TODO)
 * - Foot notes (TODO)
 * - Cross references, with full quote
 * - Set bookmark at this verse/chapter (TODO)
 * - If in Editor, it adds more functions
 *
 * Call this for a single verse (or small range) only, because
 * - it needs a lot of space, a lot of information
 * - it hits the server multiple times, to get the cross ref quotes
 * - thus, it's slow, too
 *
 * @param bv {BibleText}
 * @param linkedObjs {Array of Detail}   Objects relevant for this verse
 * @param $container {JQuery element}   where to add the sidebar element
 * @param navFunc {Function}
 * @param inline {Boolean}   true, if the verse is part of a chapter
 *    false, if it's an object page by itself
 *    if true, add close button and prevent double calls
 */
function showVerseExtras(p) {
  if (p.inline && p.$container.children(".sidebar").size() > 0) {
    // don't add multiple times
    return;
  }
  var $container;
  if (p.inline) {
    $container = $("<div class='sidebar box'/>").appendTo(p.$container);
  } else {
    $container = p.$container;
  }
  var bv = p.bv;
  console.log("show verse extras for " + bv.codeRef);

  // Linked objects
  if (p.inline && p.linkedObjs.length > 0) {
    uiSectionTitle({
      container: $container,
      text : tr("page.bible.objs.section"),
    });
    uiList({
      container : $container,
      columns : [
        { label : tr("page.bible.objs.th"), displayFunc : function(o) { return o.name; } },
      ],
      data : p.linkedObjs,
      clickFunc : function(obj) { p.navFunc(obj, persons, tr("page.bible.objs.hl", bv.name)); },
    });
  }

  // Commands
  var $buttons = $("<div id='bible-commands' class='button-list'/>").appendTo($container);

  // Cross references
  var $crossrefs = $("<div class='crossrefs'/>").appendTo($container);
  // load from server or cache. Don't do that in loop.
  bv.findCrossReferences(function(crossRefs) { // load from server or cache
    if (crossRefs.length > 0) {
      $crossrefs.addClass("box");
      var $sectionHeader = $("<div/>");
      $crossrefs.before($sectionHeader);
      uiSectionTitle({
        container: $sectionHeader,
        text : tr("page.bible.crossrefs.section"),
      });
    }
    crossRefs.forEach(function(ref) {
      var $ref = $("<div class='bible-ref'/>").appendTo($crossrefs);
      var $name = $("<span class='name clickable'/>").appendTo($ref).text(ref.prettyName);
      $name.click(function() {
        p.navFunc(ref);
      });
      ref.load(function() {
        $("<span class='quote'/>").appendTo($ref).text(ref.quote);
        var $ch = $("<span class='go-to-chapter clickable'>…</span>").appendTo($ref);
        $ch.click(function() {
          p.navFunc(ref.wholeChapter(true));
        });
      });
    });
  }, errorNonCritical);

  // Foot notes
  var $footnotes = $("<div class='footnotes'/>").appendTo($container);
  // load from server or cache. Don't do that in loop.
  bv.findFootnotes(function(footnotes) {
    var first = true;
    for (var quote in footnotes) {
      if (first) {
        first = false;
        $footnotes.addClass("box");
        var $sectionHeader = $("<div/>");
        $footnotes.before($sectionHeader);
        uiSectionTitle({
          container: $sectionHeader,
          text : tr("page.bible.footnotes.section"),
        });
      }
      var footnote = footnotes[quote];
      if (quote.length > 30) {
        quote = "…" + quote.substr(-30); // last 30 chars
      }
      var $footnote = $("<div class='bible-footnote'/>").appendTo($footnotes);
      $("<span class='quote'/>").appendTo($footnote).text(quote);
      $("<span class='footnote'/>").appendTo($footnote).text(footnote);
    };
  }, errorNonCritical);

  // Index - sources
  var $index = $("<div class='index'/>").appendTo($container);
  gStorage.cache.annotation.loadForBibleText(bv, function(refs) {
    if (refs.length == 0) {
      return;
    }
    uiSectionTitle({
      container: $index,
      text :  tr("page.bible.index.section"),
    });
    refs.forEach(function(ref) {
      ref.title = ref.title.replace(/ /g, " ").replace(/[“„]/g, '"');
      console.log(ref.title + " " + ref.pubURL);
      var isInsight = ref.pubURL.indexOf("/120000") > 0;
      //var isInsight = ref.pubRef.substr(0, 2) == "it" || /\d/.test(ref.pubRef[0]);
      ref.pubRef = isInsight ? "" : ref.pubRef;
      var $source = $("<div class='bible-source'/>").appendTo($index);
      var $title = $("<span class='title'/>").appendTo($source)
          .text(ref.title);
      var $ref = $("<span class='ref'/>").appendTo($source)
          .text(ref.pubRef);
      var $descr = uiDescr({
        container : $source,
        text : ref.articleText,
      });
      enhanceDOMTextWithLinks({
        container : $descr,
        objs : [],
        navFunc : p.navFunc,
        errorCallback : p.errorCallback,
      });

      if (isInsight) {
        var idExt = ref.pubURL.substr(ref.pubURL.indexOf("/120000") + 7, 4);
        var obj;
        gStorage.iterate(function(o) {
          if (o.idExt && o.idExt.substr(0, 7) == "it-" + idExt) {
            obj = o;
          }
        }, function() {
          if (obj) {
            $title.addClass("clickable");
            $title.click(function() {
              p.navFunc(obj);
            });
          }
        }, p.errorCallback);
      }
    });
  }, errorNonCritical);

  var $bookmark = uiButton({
    $container : $buttons,
    title : tr("page.bible.setbookmark.button"),
    classes : "set-bookmark bible-menu action",
    errorCallback : p.errorCallback,
    clickCallback : function() {
      var ch = bv.wholeChapter();
      gBibleBookmark.changeTo(ch);

      // give some visual feedback
      $bookmark.attr("disabled", "true");
      p.navFunc(ch);
    },
  });

  if (p.inline) {
    var $close = uiButton({
      $container : $buttons,
      title : tr("page.bible.close.button"),
      classes : "close bible-menu",
      errorCallback : p.errorCallback,
      clickCallback : function() {
        $sidebar.remove();
      },
    });
  }

  var $addToNotes = uiButton({
    $container : $buttons,
    title : tr("page.bible.addtonotes.button"),
    classes : "add-to-notes bible-menu action",
    errorCallback : p.errorCallback,
    clickCallback : function() {
      var quote = bv.quote ? (" " + bv.quote.replace(/\n/g, " ").trim()) : "";
      var add = bv.codeRef + quote;
      var notes = noteLoad(); // notes.js
      notes += (notes.substr(-1, 1) == "\n" ? "" : "\n") + add + "\n";
      noteSave(notes); // notes.js

      // give some visual feedback
      $addToNotes.attr("disabled", "true");
    },
  });
}
