(function () {
    var OCC_LIMIT = 7;
    var PER_PAGE = 50;

    function store() { return window.__CHAPTER_DATA__ || {}; }
    function index() { return window.__INDEX__ || { roots: {}, pages: {} }; }
    function rootRows(root) { return (window.__ROOTS__ || {})[root] || []; }
    function lookupData() { return window.__LOOKUP__ || { words: {}, bases: {} }; }
    function versesData() { return window.__VERSES__ || {}; }
    function enData() { return window.__EN__ || {}; }
    function lemmaData() { return window.__LEMMAS__ || {}; }

    var chapterCache = {};
    var pending = {};

    function ensureChapter(chapter, cb) {
        if (chapterCache[chapter]) { cb(chapterCache[chapter]); return; }
        if (pending[chapter]) { pending[chapter].push(cb); return; }
        pending[chapter] = [cb];
        var previous = window.__CHAPTER_DATA__;
        var el = document.createElement('script');
        el.src = 'assets/data/chapter-' + chapter + '.js';
        function done(data) {
            chapterCache[chapter] = data;
            window.__CHAPTER_DATA__ = previous;
            var waiting = pending[chapter];
            pending[chapter] = null;
            waiting.forEach(function (fn) { fn(data); });
        }
        el.onload = function () { done(window.__CHAPTER_DATA__ || {}); };
        el.onerror = function () { done({}); };
        document.head.appendChild(el);
    }

    function withChapter(chapter, cb) {
        var s = store();
        if (s.verses && s.verses[chapter + '-1'] !== undefined) { cb(s); return; }
        ensureChapter(chapter, cb);
    }

    function esc(s) {
        return String(s == null ? '' : s)
            .replace(/&/g, '&amp;').replace(/</g, '&lt;')
            .replace(/>/g, '&gt;').replace(/"/g, '&quot;');
    }

    function b64enc(str) {
        return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
            function (m, p) { return String.fromCharCode('0x' + p); }));
    }

    function b64dec(str) {
        try {
            return decodeURIComponent(atob(str).split('').map(function (c) {
                return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
            }).join(''));
        } catch (e) { return ''; }
    }

    function param(name) {
        var m = new RegExp('[?&]' + name + '=([^&#]*)').exec(location.search);
        return m ? decodeURIComponent(m[1].replace(/\+/g, ' ')) : '';
    }

    function pageOf(chapter, verse) {
        var b = index().pages[chapter];
        if (!b) { return 1; }
        for (var i = 0; i < b.length; i++) {
            if (verse <= b[i]) { return i + 1; }
        }
        return b.length;
    }

    function chapterFile(chapter, page) {
        return page === 1 ? chapter + '.html' : chapter + '-p' + page + '.html';
    }

    function verseHref(chapter, verse, word) {
        var u = chapterFile(chapter, pageOf(chapter, verse)) + '?anchor=' + verse;
        if (word) { u += '&word=' + word; }
        return u + '#' + verse;
    }

    function refList(rows) {
        return rows.map(function (r) {
            return "<a href='" + verseHref(r[0], r[1]) + "'>"
                + esc(r[0] + ':' + r[1]) + '</a>';
        }).join(', ');
    }

    function highlightArabic(text, forms) {
        var list = (forms || []).filter(Boolean);
        if (!list.length) { return esc(text); }
        var ranges = [];
        list.forEach(function (f) {
            var from = 0, i;
            while ((i = text.indexOf(f, from)) !== -1) {
                ranges.push([i, i + f.length]);
                from = i + f.length;
            }
        });
        if (!ranges.length) { return esc(text); }
        ranges.sort(function (a, b) { return a[0] - b[0] || b[1] - a[1]; });
        var merged = [], cur = ranges[0];
        for (var k = 1; k < ranges.length; k++) {
            if (ranges[k][0] <= cur[1]) {
                cur[1] = Math.max(cur[1], ranges[k][1]);
            } else {
                merged.push(cur);
                cur = ranges[k];
            }
        }
        merged.push(cur);
        var out = '', pos = 0;
        merged.forEach(function (r) {
            out += esc(text.slice(pos, r[0]));
            out += "<span class='highlight'>" + esc(text.slice(r[0], r[1]))
                 + '</span>';
            pos = r[1];
        });
        return out + esc(text.slice(pos));
    }

    function highlightText(html, term) {
        if (!term) { return html; }
        var re = new RegExp(term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi');
        return html.replace(/<[^>]*>|[^<]+/g, function (seg) {
            if (seg.charAt(0) === '<') { return seg; }
            return seg.replace(re, function (hit) {
                return '<span class="highlight">' + hit + '</span>';
            });
        });
    }

    function reveal(blockID, html) {
        var el = document.getElementById(blockID);
        if (!el) { return; }
        $(el).html(html === undefined || html === null ? '' : html).toggle();
    }

    function noteBlockId(chapter, verse, note) {
        var id = chapter + '-' + verse + '-' + note;
        if (chapter != 1 && verse == 0 && note == 0
                && document.getElementById(id + '-0')) {
            id += '-0';
        }
        return id;
    }

    window.showComment = function (chapter, verse, note, number) {
        var key = chapter + '-' + verse + '-' + note;
        withChapter(chapter, function (d) {
            reveal(noteBlockId(chapter, verse, note), (d.notes || {})[key]);
            $("#close-" + chapter + '-' + verse).show();
            if (verse == 0) { $("#close-" + chapter + '-1').show(); }
        });
    };

    function openAllNotes(chapter, verse) {
        withChapter(chapter, function (d) {
            var prefix = chapter + '-' + verse + '-';
            Object.keys(d.notes || {}).forEach(function (k) {
                if (k.indexOf(prefix) !== 0) { return; }
                var el = document.getElementById(
                    noteBlockId(chapter, verse, k.slice(prefix.length)));
                if (el) { $(el).html(d.notes[k]).show(); }
            });
            $("#close-" + chapter + '-' + verse).show();
        });
    }

    window.showTranslations = function (chapter, verse) {
        var key = chapter + '-' + verse;
        withChapter(chapter, function (d) {
            reveal('translations-' + key + '-0', (d.translations || {})[key]);
            $("#close-" + chapter + '-' + verse).show();
        });
    };

    function occRefLink(sp) {
        var parts = String(sp).split(':');
        return "<a target='_blank' href='"
            + verseHref(+parts[0], +parts[1], +parts[2]) + "'>"
            + esc(sp) + '</a>';
    }

    function occurrenceList(refs, more) {
        if (!refs || !refs.length) { return ''; }
        var out = refs.slice(0, OCC_LIMIT).map(occRefLink).join(', ');
        return more ? out + '...' : out;
    }

    function arabicSpan(text) {
        return '<span class="me_quran" style="font-size:26px;">'
            + esc(text) + '</span>';
    }

    function lookupHref(type, term, word) {
        var u = 'lookup.html?type=' + type;
        if (type === 'root') {
            u += '&roots=' + encodeURIComponent(b64enc(term));
            if (word) { u += '&word=' + encodeURIComponent(b64enc(word)); }
        } else {
            u += '&word=' + encodeURIComponent(b64enc(term));
        }
        return u;
    }

    function renderCorpus(words, chapter, verse) {
        var html = '<button type="button" class="close" aria-label="Close" '
            + 'onclick="javascript:close4(' + chapter + ',' + verse + ');">'
            + '<span aria-hidden="true">&times;</span></button>';
        for (var i = 0; i < words.length; i++) {
            var w = words[i], root = w[3];
            html += '<p>' + (i + 1) + '. Word: '
                + '<a target="_blank" href="' + lookupHref('arabic', w[0])
                + '">' + arabicSpan(w[0]) + '</a>';
            if (w[1]) {
                html += ' | Grammatical form: ' + (w[6]
                    ? '<a target="_blank" href="' + esc(w[6]) + '">'
                        + esc(w[1]) + '</a>'
                    : esc(w[1]));
            }
            if (w[2]) {
                html += ' | Base form: <a target="_blank" href="'
                    + lookupHref('word', w[2]) + '">' + arabicSpan(w[2])
                    + '</a>';
            }
            if (root) {
                var slot = index().roots[root] || {};
                html += ' | Root letters: '
                    + '<span class="me_quran" style="font-size:26px;">'
                    + '<a target="_blank" href="'
                    + lookupHref('root', root, w[0]) + '">' + esc(root)
                    + '</a></span>';
                var occ = occurrenceList(w[4], w[5]);
                if (occ) { html += ' | Root occurrences: ' + occ; }
                if (slot.lex !== undefined) {
                    html += ' | <a target="_blank" href="' + esc(slot.lex)
                        + '">Lane’s Lexicon</a>';
                }
                if (slot.dic !== undefined) {
                    html += ' | <a target="_blank" href="' + esc(slot.dic)
                        + '">All dictionaries</a>';
                }
            }
            html += '</p>';
        }
        return html;
    }

    window.showCorpus = function (chapter, verse) {
        var key = chapter + '-' + verse;
        withChapter(chapter, function (d) {
            var words = (d.corpus || {})[key];
            reveal('corpus-' + key + '-0',
                   words && words.length ? renderCorpus(words, chapter, verse)
                                         : undefined);
            $("#close-" + chapter + '-' + verse).show();
        });
    };

    window.showArticleFootnote = function () { };

    window.showCopy = function (chapter, verse, type) {
        var key = chapter + '-' + verse;
        withChapter(chapter, function (d) {
            var v = (d.verses || {})[key];
            if (!v) { return; }
            var text = type === 'arabic' ? v.arabic
                     : type === 'english' ? v.english
                     : v.arabic + '\n\n' + v.english;
            if (typeof copyToClipboard === 'function') { copyToClipboard(text); }
        });
    };

    function versePanels(chapter, verse) {
        var out = [], prefix = chapter + '-' + verse + '-';
        var divs = document.getElementsByTagName('div');
        for (var i = 0; i < divs.length; i++) {
            if (divs[i].id && divs[i].id.indexOf(prefix) === 0) { out.push(divs[i]); }
        }
        ['corpus-' + chapter + '-' + verse + '-0',
         'translations-' + chapter + '-' + verse + '-0'].forEach(function (id) {
            var el = document.getElementById(id);
            if (el) { out.push(el); }
        });
        return out;
    }

    function syncCloseButton(chapter, verse) {
        var btn = document.getElementById('close-' + chapter + '-' + verse);
        if (!btn) { return; }
        var open = versePanels(chapter, verse).filter(function (el) {
            return el.offsetParent !== null;
        }).length;
        btn.style.display = open ? '' : 'none';
    }

    window.close2 = function (chapter, verse) {
        versePanels(chapter, verse).forEach(function (el) {
            el.style.display = 'none';
        });
        if (verse == 1) {
            [chapter + '-0-0-0', chapter + '-0-0', chapter + '-0-1']
                .forEach(function (id) {
                    var el = document.getElementById(id);
                    if (el) { el.style.display = 'none'; }
                });
        }
        syncCloseButton(chapter, verse);
    };

    window.close3 = function (chapter, verse, note) {
        var el = document.getElementById(noteBlockId(chapter, verse, note));
        if (el) { $(el).toggle(); }
        syncCloseButton(chapter, verse);
    };

    window.close4 = function (chapter, verse) {
        var el = document.getElementById('corpus-' + chapter + '-' + verse + '-0');
        if (el) { el.style.display = 'none'; }
        syncCloseButton(chapter, verse);
    };

    window.close5 = function (chapter, verse) {
        var el = document.getElementById('translations-' + chapter + '-' + verse + '-0');
        if (el) { el.style.display = 'none'; }
        syncCloseButton(chapter, verse);
    };

    function markWord(el, position) {
        var parts = el.textContent.split(/(\s+)/);
        var seen = 0, out = '';
        for (var i = 0; i < parts.length; i++) {
            if (!parts[i] || /^\s+$/.test(parts[i])) {
                out += esc(parts[i]);
                continue;
            }
            seen++;
            out += seen === position
                ? "<span class='highlight'>" + esc(parts[i]) + '</span>'
                : esc(parts[i]);
        }
        el.innerHTML = out;
    }

    function highlightAnchor() {
        var v = param('anchor') || (location.hash || '').replace('#', '');
        if (!v || !/^\d+$/.test(v)) { return; }
        var row = document.getElementById(v);
        if (!row) { return; }
        row.classList.add('table-warning');
        var word = parseInt(param('word'), 10);
        if (word > 0) {
            var cell = row.querySelector('.arabicData .me_quran')
                || row.querySelector('.arabicData p');
            if (cell) { markWord(cell, word); }
        }
        if (row.scrollIntoView) { row.scrollIntoView({ block: 'center' }); }
    }

    function rootLetters(root) { return root.split(/\s+/).filter(Boolean); }

    function pageHref(n) {
        var parts = location.search.replace(/^\?/, '').split('&')
            .filter(function (kv) { return kv && kv.indexOf('page=') !== 0; });
        if (n > 1) { parts.push('page=' + n); }
        var file = location.pathname.split('/').pop();
        return parts.length ? file + '?' + parts.join('&') : file;
    }

    function innerPara(html) {
        var m = /^\s*<p[^>]*>([\s\S]*)<\/p>\s*$/.exec(html || '');
        return m ? m[1] : (html || '');
    }

    function noteNumbers(html) {
        var seen = {}, out = [], re = /showComment\((\d+),\s*(\d+),\s*(\d+),/g, m;
        while ((m = re.exec(html || ''))) {
            if (!seen[m[3]]) { seen[m[3]] = 1; out.push(m[3]); }
        }
        return out;
    }

    function panelRow(id) {
        return "<tr class='no-padding'><td colspan=\"3\" class='no-padding'>"
            + '<div id="' + id + '" class="alert alert-dark"'
            + ' style="display:none;"></div></td></tr>';
    }

    function copyItem(label, text) {
        return '<a onclick="copyToClipboard(\'' + b64enc(text) + '\');"'
            + ' class="dropdown-item" href="javascript:void(0);">'
            + label + '</a>';
    }

    function divider() {
        return '<li><hr class="dropdown-divider"></li>';
    }

    function lookupRow(chapter, verse, forms, term) {
        var key = chapter + '-' + verse;
        var vd = versesData()[key];
        if (!vd) { return ''; }
        var english = vd[0], arabic = vd[1];
        var cell = enData()[key];
        var body = cell ? innerPara(cell) : esc(english);
        body = body.replace(/^\s*<sup><b>\d+<\/b><\/sup>(?:&nbsp;|\s)*/, '');
        body = highlightText(body, term);
        var href = verseHref(chapter, verse);
        var ref = chapter + ':' + verse;
        var dd = 'dropdownMenuLink-' + key;

        var row = '<tr class="post-item word_lookup">'
            + '<td id="' + verse + '" width="45%" style="text-align:right;"'
            + ' class="arabicData me_quran"><p class="no-padding">'
            + highlightArabic(arabic, forms) + '</p></td>'
            + '<td style="padding-left:0;padding-right:0;">'
            + '<div class="dropdown show">'
            + '<a class="btn2 dropdown-toggle" href="#" id="' + dd + '"'
            + ' data-toggle="dropdown" aria-haspopup="true"'
            + ' aria-expanded="false"></a>'
            + '<div class="dropdown-menu" id="dm-' + key + '"'
            + ' aria-labelledby="' + dd + '">'
            + '<a onclick="showAllNotes' + chapter + verse + '();"'
            + ' class="dropdown-item" href="javascript:void(0);">Notes</a>'
            + '<a onclick="showTranslations(\'' + chapter + '\', \'' + verse
            + '\');" class="dropdown-item"'
            + ' href="javascript:void(0);">Translations</a>'
            + '<a onclick="showCorpus(\'' + chapter + '\', \'' + verse
            + '\', \'arabic\');" class="dropdown-item"'
            + ' href="javascript:void(0);">Arabic grammar</a>'
            + divider()
            + '<a onclick="close2(\'' + chapter + '\', \'' + verse + '\')"'
            + ' class="dropdown-item" href="javascript:void(0);">'
            + 'Close all panels</a>'
            + divider()
            + copyItem('Copy Arabic', arabic + '\n(' + ref + ')')
            + copyItem('Copy English', english + '\n(' + ref + ')')
            + copyItem('Copy both', arabic + '\n' + english + '\n(' + ref + ')')
            + copyItem('Copy link', href)
            + '</div></div></td>'
            + '<td width="55%" class="englishData">'
            + '<p class="alphabet0 no-padding">'
            + "<span class='ajax_lookup'><a target='_blank' class='ajax_lookup'"
            + " href='" + href + "'>" + esc(ref) + '</a> </span>'
            + body + '</p></td></tr>';

        row += panelRow(key + '-0');
        noteNumbers(cell).forEach(function (num) {
            if (num !== '0') { row += panelRow(key + '-' + num); }
        });
        row += panelRow('translations-' + key + '-0');
        row += panelRow('corpus-' + key + '-0');
        return row;
    }

    function defineNoteOpeners(rows) {
        rows.forEach(function (r) {
            var chapter = r[0], verse = r[1];
            window['showAllNotes' + chapter + verse] = function () {
                openAllNotes(chapter, verse);
            };
        });
    }

    function pagerRow(page, pages, total) {
        function numbers(from, to) {
            var out = '';
            for (var i = from; i <= to; i++) {
                out += '<li class="page-item' + (i === page ? ' active' : '')
                    + '"><a class="page-link" href="' + pageHref(i) + '">'
                    + i + '</a></li>';
            }
            return out;
        }
        function run(prev, next, all) {
            var out = '<li class="page-item' + (page === 1 ? ' disabled' : '')
                + '"><a class="page-link" href="'
                + (page === 1 ? '' : pageHref(page - 1)) + '">' + prev
                + '</a></li>';
            if (pages > 1) {
                if (all) {
                    out += numbers(1, pages);
                } else {
                    var from = Math.max(1, Math.min(page - 2, pages - 4));
                    out += numbers(from, Math.min(pages, from + 4));
                }
            }
            return out + '<li class="page-item'
                + (page === pages ? ' disabled' : '') + '">'
                + '<a class="page-link" href="'
                + (page === pages ? '' : pageHref(page + 1)) + '">' + next
                + '</a></li>';
        }
        var tally = '<p>Page ' + page + ' of ' + pages + ' | ' + total
            + ' verse(s) total</p>';
        return '<tr><td colspan="3" align="center">'
            + '<div class="paginator d-lg-none">'
            + '<nav aria-label="Page navigation">'
            + '<ul class="pagination">' + run('&lt;', '&gt;', false) + '</ul>'
            + '<ul class="pagination d-none d-lg-block">'
            + run('Previous', 'Next', true) + '</ul>'
            + '</nav>' + tally + '</div>'
            + '<div class="paginator d-none d-lg-block">'
            + '<nav aria-label="Page navigation">'
            + '<ul class="pagination">' + run('Previous', 'Next', true)
            + '</ul></nav>' + tally + '</div>'
            + '</td></tr>';
    }

    function renderRows(head, rows, term) {
        var page = parseInt(param('page'), 10) || 1;
        var pages = Math.max(1, Math.ceil(rows.length / PER_PAGE));
        if (page > pages) { page = pages; }
        var slice = rows.slice((page - 1) * PER_PAGE, page * PER_PAGE);

        var html = head + '<table class="table"><tbody class="posts-list">';
        slice.forEach(function (r) {
            html += lookupRow(r[0], r[1], r[2], term);
        });
        html += pagerRow(page, pages, rows.length) + '</tbody></table>';
        defineNoteOpeners(slice);
        return html;
    }

    function outputBox() {
        var el = document.getElementById('offline-results');
        if (el) { return el; }
        el = document.createElement('div');
        el.id = 'offline-results';
        document.body.appendChild(el);
        return el;
    }

    function filterHref(root, word, lemma) {
        var u = 'lookup.html?type=root&roots='
            + encodeURIComponent(b64enc(root));
        if (word) { u += '&word=' + encodeURIComponent(b64enc(word)); }
        return u + '&filters=' + encodeURIComponent(b64enc(lemma));
    }

    var FILTER_STYLE = '<style> .filter li { display: inline-block;'
        + " font-size: 22px; font-family: 'Cambria Regular'; text-align:"
        + ' center; padding: 10px 10px 10px 0px; } .filter li:before {'
        + ' content: " | "; } .filter li:first-child:before { content: "";'
        + ' } </style>';

    function filterList(root, word, active) {
        var slot = lemmaData()[root];
        if (!slot || !slot.l || !slot.l.length) { return ''; }

        function entry(label, count, lemma, isActive) {
            if (isActive) {
                return '<li >' + label + "<br/><span dir='ltl'>("
                    + count + ')</span></li>';
            }
            var href = filterHref(root, word, lemma);
            return "<li ><a href='" + href + "'>" + label + '</a>'
                + "<br/><span dir='ltl'><a href='" + href + "'>("
                + count + ')</a></span></li>';
        }

        var html = FILTER_STYLE + "<ul class='filter text-center'>";
        html += entry('All', slot.t, 'All', !active);
        slot.l.forEach(function (row) {
            html += entry(esc(row[0]), row[1], row[0], active === row[0]);
        });
        return html + '</ul>';
    }

    function heading(type, term, rows, extra, opts) {
        opts = opts || {};
        var span = '<span class="arabicData me_quran">' + esc(term) + '</span>';
        var text;
        if (type === 'root') {
            text = '<span id="total-count">' + rows.length + '</span> verses'
                + ' found containing words formed by the root letters ' + span;
            text += opts.filter
                ? " and filtered by <span class='arabicData me_quran'>"
                    + esc(opts.filter) + '</span>. '
                : ' . ';
        } else if (type === 'word') {
            text = '<span id="total-count">' + rows.length + '</span> verses'
                + ' found containing words of the form ' + span + ' found. ';
        } else {
            text = '<span id="total-count">' + rows.length + '</span> verses'
                + ' containing ' + span + ' found. ';
        }
        text += '<a class="show-more" href="#">See all</a>.';
        if (extra) { text += '<br />' + extra + '<br />'; }
        if (type === 'root') {
            text += filterList(term, opts.word, opts.filter);
        }
        return '<div class="englishData">'
            + '<p class="text-center englishData">' + text + '</p>'
            + '<div id="search" class="hideContent alert alert-dark"'
            + ' style="display:none;">' + refList(rows) + '</div></div>';
    }

    function bindShowMore() {
        $(document).off('click.qmore').on('click.qmore', '.show-more',
            function (e) {
                e.preventDefault();
                var label = $('.show-more').text().toUpperCase();
                $('#search').toggle();
                $('.show-more').text(label === 'SEE ALL' ? 'Remove all'
                                                         : 'See all');
            });
    }

    function runLookup() {
        var type = param('type');
        if (!type) { return false; }
        if (!window.__ROOTS__ || !window.__LOOKUP__) {
            location.replace('lookup.html' + location.search + location.hash);
            return true;
        }
        var rows = [], term = '', extra = '', opts = {};
        if (type === 'root') {
            term = b64dec(param('roots'));
            var slot = index().roots[term];
            rows = rootRows(term);
            opts.word = param('word') ? b64dec(param('word')) : '';
            var chosen = param('filters') ? b64dec(param('filters')) : '';
            if (chosen && chosen !== 'All') {
                opts.filter = chosen;
                rows = lookupData().bases[chosen]
                    || lookupData().words[chosen] || [];
            }
            if (slot && slot.dic) {
                extra += '<a target="_blank" href="' + esc(slot.dic)
                    + '">All dictionaries</a>';
            }
            if (slot && slot.lex) {
                extra += (extra ? ' | ' : '') + '<a target="_blank" href="'
                    + esc(slot.lex) + '">Lane’s Lexicon</a>';
            }
        } else if (type === 'word') {
            term = b64dec(param('word'));
            rows = lookupData().bases[term] || [];
        } else {
            term = b64dec(param('word'));
            rows = lookupData().words[term] || [];
        }
        outputBox().innerHTML = renderRows(
            heading(type, term, rows, extra, opts), rows, '');
        bindShowMore();
        return true;
    }

    function fold(s) {
        s = String(s);
        if (s.normalize) {
            s = s.normalize('NFD').replace(/[̀-ͯ]/g, '');
        }
        return s.toLowerCase();
    }

    var folded = null;

    function foldedVerses() {
        if (folded) { return folded; }
        var v = versesData();
        folded = [];
        Object.keys(v).forEach(function (k) {
            var p = k.split('-');
            if (p[1] === '0') { return; }
            folded.push([+p[0], +p[1], fold(v[k][0])]);
        });
        folded.sort(function (a, b) { return a[0] - b[0] || a[1] - b[1]; });
        return folded;
    }

    function searchVerses(query) {
        var needle = fold(query), hits = [];
        if (!needle) { return hits; }
        foldedVerses().forEach(function (r) {
            if (r[2].indexOf(needle) !== -1) { hits.push([r[0], r[1], []]); }
        });
        return hits;
    }

    function runSearch() {
        var q = param('q');
        if (!q) { return false; }
        var term = q.trim();
        var ref = /^(\d+)\s*:\s*(\d+)$/.exec(term);
        if (ref && versesData()[ref[1] + '-' + ref[2]]) {
            location.replace(verseHref(+ref[1], +ref[2]));
            return true;
        }
        var hits = searchVerses(term);
        if (!hits.length) { location.replace('1.html'); return true; }
        var head = '<div class="englishData">'
            + '<p class="text-center englishData"><span id="total-count">'
            + hits.length + '</span> verse' + (hits.length === 1 ? '' : 's')
            + ' found containing <i>' + esc(term) + '.</i> '
            + '<a class="show-more" href="#">See all</a>.</p>'
            + '<div id="search" class="hideContent alert alert-dark"'
            + ' style="display:none;">' + refList(hits) + '</div></div>';
        outputBox().innerHTML = renderRows(head, hits, term);
        bindShowMore();
        return true;
    }

    function initRootSearch() {
        var r1 = document.getElementById('root1');
        if (!r1) { return; }
        var roots = Object.keys(index().roots);
        if (!roots.length) { return; }
        var split = roots.map(rootLetters);
        var sels = [r1, document.getElementById('root2'),
                    document.getElementById('root3'),
                    document.getElementById('root4')];
        $(sels.filter(Boolean)).off('change');

        function nextLetters(prefix) {
            var seen = {};
            for (var i = 0; i < split.length; i++) {
                var s = split[i];
                if (s.length <= prefix.length) { continue; }
                var ok = true;
                for (var j = 0; j < prefix.length; j++) {
                    if (s[j] !== prefix[j]) { ok = false; break; }
                }
                if (ok) { seen[s[prefix.length]] = 1; }
            }
            return Object.keys(seen).sort();
        }

        function clear(sel) {
            if (!sel) { return; }
            sel.innerHTML = '';
            sel.disabled = true;
        }

        function fill(sel, values) {
            if (!sel) { return; }
            sel.innerHTML = '';
            sel.add(new Option(''));
            values.forEach(function (v) { sel.add(new Option(v)); });
            sel.disabled = false;
        }

        function picked(upto) {
            var out = [];
            for (var i = 0; i < upto; i++) {
                var v = sels[i] && sels[i].value;
                if (!v || v === '0') { break; }
                out.push(v);
            }
            return out;
        }

        function empty(sel) {
            var v = sel.value;
            return !v || v === '0';
        }

        clear(sels[1]);
        clear(sels[2]);
        clear(sels[3]);

        r1.addEventListener('change', function () {
            if (empty(r1)) {
                clear(sels[1]); clear(sels[2]); clear(sels[3]);
                return;
            }
            fill(sels[1], nextLetters(picked(1)));
            clear(sels[2]);
            clear(sels[3]);
        });

        if (sels[1]) {
            sels[1].addEventListener('change', function () {
                if (empty(sels[1])) {
                    clear(sels[2]); clear(sels[3]);
                    return;
                }
                fill(sels[2], nextLetters(picked(2)));
                clear(sels[3]);
            });
        }

        if (sels[2]) {
            sels[2].addEventListener('change', function () {
                if (empty(sels[2])) { clear(sels[3]); return; }
                var more = nextLetters(picked(3));
                if (more.length) { fill(sels[3], more); } else { clear(sels[3]); }
            });
        }

        var form = document.getElementById('arabic_advanced_search');
        if (form) {
            form.addEventListener('submit', function (e) {
                e.preventDefault();
                var c = picked(4);
                if (!c.length) { return; }
                var target = c.join(' ');
                for (var i = 0; i < roots.length; i++) {
                    if (rootLetters(roots[i]).join(' ') === target) {
                        location = lookupHref('root', roots[i]);
                        return;
                    }
                }
            });
        }
    }

    function initTextSearch() {
        $(document).off('submit.qsearch')
            .on('submit.qsearch', 'form#searchGotoForm', function (e) {
                e.preventDefault();
                var q = $(this).find('input[name=searchInput]').val();
                if (q && q.trim()) {
                    location = 'search.html?q=' + encodeURIComponent(q.trim());
                }
            });
    }

    function preloadChapter() {
        if (!window.__CHAPTER__) { return; }
        window.addEventListener('load', function () {
            ensureChapter(window.__CHAPTER__, function () { });
        });
    }

    $(function () {
        highlightAnchor();
        initTextSearch();
        if (!runLookup()) { runSearch(); }
        initRootSearch();
        preloadChapter();
    });
}());
