/**
 * Scripturizer for Javascript.
 *
 * Link scripture references to ESV at Good News Publisher or Bible Gateway.
 * Instead of having a server side solution in Perl or PHP, the Javascript
 * version provides a solution to drop into any web page and then
 * automatically scan through the document and generate links.
 *
 * For more information, see
 *
 *   http://scott.yang.id.au/project/scripturizer
 *
 * @author Scott Yang <scotty@yang.id.au>
 * @version 1.2
 */ 

/*************************************************************************
 * Configuration section - Here is the place where you can tune the behaviour
 * of Scripturizer for Javascript.
 *************************************************************************/

var Scripturizer = {
    /**
     * Whether to automatically scripturize a section of the HTML document, by
     * binding the "Scripturizer.doDocument" to window.onload() event.
     */
    onload: true,

    /**
     * The document element ID used by Scripturize.doDocument(). If it is
     * empty, or the element cannot be found, then document.body will be used,
     * i.e. the entire document will be passed through scripturizer.
     */
    element: 'container',

    /**
     * Version of Bible to be used. If version is 'esv', link to GNP will be
     * created. If version is 'esvpopup', and 'esvpopup.js' is loaded, then we
     * will use the ESV Popup Reference. Otherwise, link to Bible Gateway will
     * be created.
     */  
    version: 'esvpopup'
};

/*************************************************************************
 * Code section - No need to modify the code below this point.
 *************************************************************************/

Scripturizer._bg_translations = {
    'AMP':     ['45', 'Amplified Bible'],
    'ASV':     ['8"', 'American Standard Version'],
    'CEV':     ['46', 'Contemporary English Version'],
    'DARBY':   ['16', 'Darby Translation'],
    'ESV':     ['47', 'English Standard Version'],
    'HCSB':    ['77', 'Holman Christian Standard Bible'],
    'KJ21':    ['48', '21st Century King James Version'],
    'KJV':     ['9',  'King James Version'],
    'MSG':     ['65', 'The Message'],
    'NASB':    ['49', 'New American Standard Bible'],
    'NIRV':    ['76', 'New International Reader\'s Version'],
    'NIV':     ['31', 'New International Version'],
    'NIV-UK':  ['64', 'New International Version - UK'],
    'NKJV':    ['50', 'New King James Version'],
    'NLT':     ['51', 'New Living Translation'],
    'NLV':     ['74', 'New Life Version'],
    'WE':      ['73', 'Worldwide English (New Testament)'],
    'WNT':     ['53', 'Wycliffe New Testament'],
    'YLT':     ['15', 'Young\'s Literal Translation']
};

/**
 * Scripturize a plain text string.
 */
Scripturizer.addLink = function(text) {
    if (!Scripturizer._init)
        Scripturizer._initModule();

    return text.replace(Scripturizer._regexp, Scripturizer._substitute);
};

Scripturizer._hasCallback = function() {
    if (navigator.userAgent.search(/Safari/) >= 0)
	return false;
    return true;
};

/**
 * Initialise the module. It only needs to be done once to create/compile
 * regular expression object.
 */
Scripturizer._initModule = function() {
    var vol = 'I+|1st|2nd|3rd|First|Second|Third|1|2|3';
    var bok = 'Genesis|Gen|Exodus|Exod?|Leviticus|Lev|Levit?|Numbers|'+
        'Nmb|Numb?|Deuteronomy|Deut?|Joshua|Josh?|Judges|Jdg|Judg?|Ruth|Ru|'+
        'Samuel|Sam|Sml|Kings|Kngs?|Kin?|Chronicles|Chr|Chron|Ezra|Ez|'+
        'Nehemiah|Nehem?|Esther|Esth?|Job|Jb|Psalms?|Psa?|Proverbs?|Prov?|'+
        'Ecclesiastes|Eccl?|Songs?ofSolomon|Song?|Songs|Isaiah|Isa|Jeremiah|'+
        'Jer|Jerem|Lamentations|Lam|Lament?|Ezekiel|Ezek?|Daniel|Dan|Hosea|'+
        'Hos|Joel|Jo|Amos|Am|Obadiah|Obad?|Jonah|Jon|Micah|Mic|Nahum|Nah|'+
        'Habakkuk|Hab|Habak|Zephaniah|Zeph|Haggai|Hag|Hagg|Zechariah|Zech?|'+
        'Malachi|Malac?|Mal|Mat{1,2}hew|Mat?|Mark|Mrk|Luke|Lu?k|John|Jhn|Jo|'+
        'Acts?|Ac|Romans|Rom|Corinthians|Cor|Corin|Galatians|Gal|Galat|'+
        'Ephesians|Eph|Ephes|Philippians|Phili?|Colossians|Col|Colos|'+
        'Thessalonians|Thes?|Timothy|Tim|Titus|Tts|Tit|Philemon|Phil?|'+
        'Hebrews|Hebr?|James|Jam|Jms|Peter|Pete?|Jude|Ju|Revelations?|Rev|'+
        'Revel';
    var ver = '\\d+(:\\d+)?(?:\\s?[-&]\\s?\\d+)?';
    var regex = '(?:('+vol+')\\s+)?('+bok+')\\s+('+ver+'(?:\\s?,\\s?'+
        ver+')*)';

    // Check whether 'ESVPopup' variable has been initialised, i.e.
    // 'esvpopup.js' has been loaded. If not, then we will fall back to
    // external linking to GNP.
    if (Scripturizer.version == 'esvpopup') {
        try {
            ESVPopup;
        } catch (e) {
            Scripturizer.version = 'esv';
        }
    }

    Scripturizer._regexp = new RegExp(regex, "gm");

    switch (Scripturizer.version) {
        case 'esv':
        case 'esvpopup':
            Scripturizer._link = 'http://www.gnpcb.org/esv/search/?go=Go&q=';
            Scripturizer._linktext = 'English Standard Version Bible';
            break;
        default:
            var bgver = Scripturizer._bg_translations[
                Scripturizer.version.toUpperCase()];
            Scripturizer._link = 
                'http://www.biblegateway.com/passage/index.php?version='+
                bgver[0]+'&search=';
            Scripturizer._linktext = 'Bible Gateway - '+bgver[1];
    }

    // Check whether the Javascript engine supports callback function in
    // regular expression. We will make a static (but not optimal) replacement
    // in this case.
    if (! Scripturizer._hasCallback()) {
        if (Scripturizer.version == 'esvpopup') {
            Scripturizer._substitute = '<a class="scripturized" href="#" '+
                'onclick="ESVPopup.onclick(event);return false;" title="'+
                Scripturizer._linktext+'">$0</a>';
        } else {
            Scripturizer._substitute = '<a class="scirpturized" href="'+
                Scripturizer._link+'$1+$2+$3" title="'+Scripturizer._linktext+
                '">$0</a>';
        }
    }
    Scripturizer._init = true;
};

/**
 * Callback function used in regular expression replace.
 */
Scripturizer._substitute = function(match, vol, bok, ver) {
    if (Scripturizer.version == 'esvpopup') {
        return '<a class="scripturized" href="#" onclick="'+
            'ESVPopup.onclick(event);return false;" title="'+
            Scripturizer._linktext+'">'+match+'</a>';
    } else {
        var lnk = (vol ? (vol + " ") : "") + bok + (ver ? (" " + ver) : "");
        lnk = lnk.replace(' ', '+');
        lnk = lnk.replace(/[,&;]/, '%2C');
        lnk = lnk.replace(/:]/, '%3A');
        lnk = Scripturizer._link + lnk;
        return '<a class="scripturized" href="'+lnk+'" title="'+
            Scripturizer._linktext+'">'+match+'</a>';
    }
};

/**
 * Scripturize a HTML string. It tries to break the text apart to avoid the
 * content inside the tags, <script>, <style> and <textarea>.
 */
Scripturizer.doHTML = function(html) {
    var pos = 0;
    var tag = '<';
    var skip = false;
    var last = 0;
    var part = null;
    var result = '';

    while (last >= 0) {
        pos = html.indexOf(tag, last);
        if (pos < 0) {
            part = html.substring(last);
            last = -1;
        } else {
            part = html.substring(last, pos);
            last = pos+1;
        }

        if (tag == '<') {
            if (!skip)
                part = Scripturizer.addLink(part);
            else
                skip = false;
        } else if (part.match(/^(a |script|style|textarea)/i)) {
            skip = true;
        }

        result += part + (pos < 0 ? '' : tag);
        tag  = tag == '<' ? '>' : '<';
    }
    return result;
};

/**
 * Scripturize a DOM element.
 */
Scripturizer.doElement = function(element) {
    element.innerHTML = Scripturizer.doHTML(element.innerHTML);
};

/**
 * Scripturize the current document.
 */
Scripturizer.doDocument = function() {
    if ((Scripturizer.element && 
         (e = document.getElementById(Scripturizer.element))) ||
        (e = document.body))
    {
	Scripturizer.doElement(e);
    }
};

if (Scripturizer.onload) {
    if (window.onload) {
	Scripturizer._old_onload = window.onload;
	window.onload = function(ev) {
	    Scripturizer._old_onload(ev);
	    Scripturizer.doDocument();
	};
    } else {
	window.onload = Scripturizer.doDocument;
    }
}
