﻿if (!window.console)
    window.console = { log: function() { } };

if (!Array.indexOf) {
    Array.prototype.indexOf = function(obj) {
        for (var i = 0; i < this.length; i++) {
            if (this[i] == obj) {
                return i;
            }
        }
        return -1;
    }
}

$(document).ready(function() {

    bible = {};

    bible.Reader = {
        lang: 'G',

        dialog: null,

        init: function() {

            this.dialog = $('#dialog-container');
            this.dialogText = $('#dialog-text');
            this.dialogHeader = $('#dialog-header');
            //.dialog();
            //this.dialog.dialog('close');


            // reference helper
            $('#reference').addClass('firstTime').click(function(e) { $(this).removeClass('firstTime'); });


            // font choices

            // add font options
            var options = '';
            for (var size = 8; size <= 38; size += 2) {
                options += '<option value="' + size + 'px">' + size + 'px</option>';
            }
            $('select.font-size').html(options);
            $('#font-size-hebrew').val('20px');
            $('#font-size-greek').val('16px');
            
            
            options = '';
            for (var size = 80; size <= 500; size += 20) {
                options += '<option value="' + size + '%">' + size + '%</option>';
            }
            $('select.font-lineheight').html(options);
            $('#font-lineheight-hebrew').val('240%');
            $('#font-lineheight-greek').val('200%');            
            

            $('head').append('<style id="injectedFontCss" type="text/css"></style>');
            this.updateFonts();
            $('.font-family').keyup(function(e) { bible.Reader.updateFonts(); });
            $('.font-size, .font-lineheight').change(function(e) { bible.Reader.updateFonts(); });

            // setup verse change		
            $('#reference').keyup(function(e) {
                if (e.keyCode == 13) {
                    e.preventDefault();
                    bible.Reader.getReference();
                }
            });
            $('#go-button').bind('click', function(e) {
                    e.preventDefault();
                    bible.Reader.getReference();
            });

            // setup word count threshold
            $('#word-count-threshold, #show-parsing, #show-pos, #show-frequency').change(function(f) {
                bible.Reader.buildLexicalInfo();
            });

            // setup parts of speech
            $('select.pos-rule')
			.change(function(l) {
			    bible.Reader.updateStyles();
			})
			.html('<option value="">--none--</option>'
					+ '<option value="c:#910000">Red</option>'
					+ '<option value="h:#ffcccc">Red (bg)</option>'
					+ '<option value="c:#ffcc33">Orange</option>'
					+ '<option value="h:#ffcc33">Orange (bg)</option>'
					+ '<option value="c:#eeee66">Yellow</option>'
					+ '<option value="h:#eeee66">Yellow (bg)</option>'
					+ '<option value="c:#319D2D">Green</option>'
					+ '<option value="h:#aaff55">Green (bg)</option>'
					+ '<option value="c:#0000ff">Blue</option>'
					+ '<option value="h:#55AAFF">Blue (bg)</option>'
					+ '<option value="c:#AA7FFF">Purple</option>'
					+ '<option value="h:#AA7FFF">Purple (bg)</option>'
					+ '<option value="u">Underline</option>'
					+ '<option value="b">Bold</option>'
					+ '<option value="i">Italic</option>'



					);

        },

        updateFonts: function() {
            /*
            var cssText =
                'span.gk { font-family: ' + $('#font-family-greek').val() + '; font-size: ' + $('#font-size-greek').val() + '; line-height: ' + $('#font-lineheight-greek').val() + ';}' +
                'span.hb { font-family: ' + $('#font-family-hebrew').val() + '; font-size: ' + $('#font-size-hebrew').val() + '; line-height: ' + $('#font-lineheight-hebrew').val() + ';}';

            console.log(cssText);
            if ($.browser.msie) {
                $('#injectedFontCss').remove();
                $('head').append('<style id="injectedFontCss" type="text/css">' + cssText + '</style>');
            } else {
                $('#injectedFontCss').html(cssText);
            }
            */
            
           var lang = (bible.Reader.lang == 'H') ? 'hebrew' : 'greek';
           $('#bible-text').css(
							{
								'font-family':$('#font-family-' + lang).val(),
								'font-size': $('#font-size-' + lang).val(),
								'line-height':$('#font-lineheight-' + lang).val(),
							}
						);

        },

        wordOver: function(e) {
            if (!$('#show-popups').attr('checked'))
                return;

            // $(this).animate({backgroundColor: '#ffff00'}, 500);
            var o = $(this);
            o.css('color', '#666');


            var sn = o.attr('sn');
            if (!sn || parseInt(sn) < 1) return

            var pos = o.attr('pos')
            var inf = o.attr('inf');
            var d = bible.Reader.dialog;

            d.css('display', 'block');
            d.css('top', e.pageY + 5);
            d.css('left', e.pageX + 5);
            var dt = bible.Reader.dialogText;
            var dh = bible.Reader.dialogHeader;
            dh.html('');
            dt.html('loading...');

            //d.load('scraping/gbs/t-' + sn + '.html');
            //return;

            bible.Storage.getLexicalEntry(bible.Reader.lang + sn, function(data) {
                dh.html('<span class="lexical-form ' + ((bible.Reader.lang == 'G') ? 'gk' : 'hb') + '">' + data.LexicalForm + '</span> '
				+ '<span class="strongs">' + bible.Reader.lang + sn + '</span>');

                dt.html(
				'<span class="morphology">' + bible.Reader.getPartofSpeech(pos) + ', ' + bible.Reader.getMorphology(pos, inf) + '</span>'
				+ '<span class="gloss">usage: ' + data.KjvDefinition + '</span>'
				+ '<div class="outline-of-usage">' + data.OutlineOfUsage + '</dev>');
                /*
                var top = e.pageY+5;
                var left = e.pageX+5;
                var h = dt.height();
                var sTop = $(document).scrollTop();
                var vH= $(document).height();
       
			console.log(top , h , vH);
       
			if (top + h > vH) {
                top = (top + h) - vH;
                }
				
			d.css('top', top);
                d.css('left', left);
                */
            });
        },

        wordOut: function(e) {
            bible.Reader.dialog.css('display', 'none');
            /*
            var o = $(this);
            var oOff = o.offset();
            var oW = o.width();
            var oH = o.height();	
		
		function mouseWithin(mX, mY, oX, oY, oW, oH) {
            console.log(mX, mY, oX, oY, oW, oH);
            console.log('-', (mX >= oX) , (mX <= oX + oW), (mY >= oY ), ( mY <= oY + oH) );
			
			return (mX >= oX && mX <= oX + oW &&
            mY >= oY && mY <= oY + oH );
            };
		
		setTimeout(function() {
			
			var dOff = bible.Reader.dialog.offset();
            var dW = bible.Reader.dialog.width();
            var dH = bible.Reader.dialog.height();
			
			if ( !(mouseWithin( e.pageX, e.pageY, oOff.left, oOff.top, oW, oH) || mouseWithin( e.pageX, e.pageY, dOff.left, dOff.top, dW, dH) ) ) {
            bible.Reader.dialog.css('display','none');	
            }			
			
		}, 250);
            */

            // $(this).stop().css('background-color', '#ffffff');
            $(this).css('color', '');

        },




        getReference: function() {
            var ref = $('#reference').val();
            $('#bible-text').html('Loading...');
            $('#footnotes').html('');

            bible.Interface.getReference(ref, function(data) {
								console.log('got some data', data);
            
                bible.Storage.setRef(data.reference);
                $('#reference').val(data.reference);
                $('#bible-text').html(data.html);

                var book = parseInt(data.book);

                if (book > 0) {

                    bible.Reader.lang = data.lang;

                    // add verse hovers/highlight		
                    //$('#bible-text span').hover(bible.Reader.wordOver, bible.Reader.wordOut);
                    $('#bible-text span').mouseover(bible.Reader.wordOver);
                    $('#bible-text span').mouseout(bible.Reader.wordOut);

                    // text direction for greek and hebrew		
                    if (bible.Reader.lang == 'H') {
                        //if (book <= 39) { 
                        $('#bible-text').removeClass('greek');
                        $('#bible-text').addClass('hebrew');
                        //$('#bible-text').css('direction','rtl');
                    } else {
                        $('#bible-text').removeClass('hebrew');
                        $('#bible-text').addClass('greek');
                        //$('#bible-text').css('direction','ltr');
                    }


                    // RUBY?
                    if ($('word-count-display').val() == 'above') {
                        bible.Reader.createRuby();
                    } else {
                        bible.Reader.buildLexicalInfo();
                    }
                } else {
                    $('#reference').val(ref);
                    alert('Invalid reference. Try an alternate spelling.');
                }

            });
        },

        partsOfSpeech: {
            N: 'noun',
            A: 'adjective',
            T: 'article',
            V: 'verb',
            P: 'personal pronoun',
            R: 'relative pronoun',
            C: 'reciprocal pronoun',
            D: 'demonstrative pronoun',
            K: 'correlative pronoun',
            I: 'interrogative pronoun',
            X: 'indefinite pronoun',
            Q: 'correlative or interrogative pronoun',
            F: 'reflexive pronoun',
            S: 'possessive pronoun',
            ADV: 'adverb',
            CONJ: 'conjunction',
            COND: 'cond',
            PRT: 'particle',
            PREP: 'preposition',
            INJ: 'interjection',
            ARAM: 'aramaic',
            HEB: 'hebrew'
        },

        getPartofSpeech: function(pos) {
            var full = bible.Reader.partsOfSpeech[pos.toUpperCase()];

            return (full != null) ? full : '?';
        },

        nounCases: {
            'N': 'nominative',
            'V': 'vocative',
            'G': 'genitive',
            'D': 'dative',
            'A': 'accusative'
        },

        wordNumber: {
            'S': 'singular',
            'P': 'plural'
        },

        wordGender: {
            'M': 'masculine',
            'F': 'feminine',
            'N': 'neuter'
        },

        wordPerson: {
            '1': '1st',
            '2': '2nd',
            '3': '3rd'
        },

        verbTenses: {
            'P': 'present',
            'I': 'imperfect',
            'F': 'future',
            '2F': 'second future',
            'A': 'aorist',
            '2A': 'second aorist',
            'R': 'perfect',
            '2R': 'second perfect',
            'L': 'pluperfect',
            '2L': 'second pluperfect',
            'X': 'no tense stated'
        },

        verbVoices: {
            'A': 'active',
            'M': 'middle',
            'P': 'passive',
            'E': 'middle or passive',
            'D': 'middle deponent',
            'O': 'passive deponent',
            'N': 'middle or passive deponent',
            'Q': 'impersonal active',
            'X': 'no voice'
        },

        verbMoods: {
            'I': 'indicative',
            'S': 'subjunctive',
            'O': 'optative',
            'M': 'imperative',
            'N': 'infinitive',
            'P': 'participle',
            'R': 'imperative participle'
        },

        getMorphology: function(pos, info) {

            switch (pos.toUpperCase()) {
                case 'T':
                case 'N':
                    var c = bible.Reader.nounCases[info.substring(0, 1)];
                    var n = bible.Reader.wordNumber[info.substring(1, 2)];
                    var g = bible.Reader.wordGender[info.substring(2, 3)];
                    return c + ', ' + n + ', ' + ((g) ? g : '');
                case 'A':
                    var c = bible.Reader.nounCases[info.substring(0, 1)];
                    var n = bible.Reader.wordNumber[info.substring(1, 2)];
                    return c + ', ' + n;
                case 'V':
                    var t = '';
                    var rem = ''
                    if (info.substring(0, 1) == '2') {
                        t = bible.Reader.verbTenses[info.substring(0, 2)];
                        rem = info.substring(2);
                    } else {
                        t = bible.Reader.verbTenses[info.substring(0, 1)];
                        rem = info.substring(1);
                    }
                    var v = bible.Reader.verbVoices[rem.substring(0, 1)];
                    var m = bible.Reader.verbMoods[rem.substring(1, 2)];

                    if (rem.length == 2) {
                        return info + ': ' + t + ', ' + v + ', ' + m;
                    } else if (rem.length == 5) {
                        var p = bible.Reader.wordPerson[rem.substring(3, 4)];
                        var n = bible.Reader.wordNumber[rem.substring(4, 5)];
                        return t + ', ' + v + ', ' + m + ', ' + p + ', ' + n;

                    } else if (rem.length == 6) {
                        var c = bible.Reader.nounCases[rem.substring(3, 4)];
                        var n = bible.Reader.wordNumber[rem.substring(4, 5)];
                        var g = bible.Reader.wordGender[rem.substring(5, 6)];

                        return t + ', ' + v + ', ' + m + ', ' + c + ', ' + n + ', ' + g;
                    }

                    //m = bible.Reader.verbMoods[info.substring(2+offset,3+offset)];



                default:
                    return info;
            }
        },

        createRuby: function() {
           // var rubyHtml = '';
           // $('#bible-text span').each(function(
        },

        buildLexicalInfo: function() {
            var threshold = $('#word-count-threshold').val();

            // remove all words
            $('sup.def-up').remove();

            // show loading message
            $('#footnotes').html("Loading...");

            // add back to selected words
            if (threshold != '') {
                var lexicalList = [];

                var tn = parseInt(threshold);
                var index = 0;

                var showParsing = $('#show-parsing').attr('checked');
                var showFrequency = $('#show-frequency').attr('checked');

                // go through all the words, 
                // grab the ones we need to define
                var wordsNeedingWork = [];

                $('#bible-text span').each(function(f) {
                    var word = $(this);

                    // filter out verse numbers, articles, and prepositions
                    if (!word.hasClass('v-num') && !word.hasClass('pos-t') && !word.hasClass('pos-prep')) {

                        var counts = word.attr('wc').split('-');
                        var tCount = parseInt(counts[0]);
                        var bCount = parseInt(counts[1]);
                        var strongsNum = word.attr('sn');

                        // check frequency to see if we need to show this
                        if ((isNaN(tCount) || tCount <= tn || threshold == 'all') && (parseInt(strongsNum) > 0)) {

                            // if we are not showing parsing, check to see if the number can be re-used						

                            var key = strongsNum;
                            var number = 0;
                            var skip = false;

                            if (showParsing) {
                                number = ++index;
                            } else {

                                number = lexicalList.indexOf(key);

                                if (number != -1) {
                                    // this number already existed, so use one higher than the index,							
                                    number++;

                                    // but don't show the definition again
                                    skip = true;
                                } else {
                                    // since this is new, we increase the index
                                    number = ++index;
                                    lexicalList.push(key);
                                    //list += '<li><a name="foot_' + number + '"></a>' + lex + ": " + kjv + '</li>';
                                }
                            }

                            // create definition
                            if (!skip) {

                                var pos = word.attr('pos');
                                var posInfo = word.attr('inf');

                                wordsNeedingWork.push({
                                    number: number,
                                    //lex: lex,
                                    lex: '',
                                    strongsNum: strongsNum,
                                    tCount: tCount,
                                    bCount: bCount,
                                    pos: pos,
                                    posInfo: posInfo,
                                    englishGlosses: ''
                                });


                            }

                            // create superscript number
                            // could also use $.append, not sure which style looks better
                            if (bible.Reader.lang == 'H')
                                word.before('<sup class="def-up">' + number + '</sup>');
                            else
                                word.after('<sup class="def-up">' + number + '</sup>');
                        }
                    }
                });

                console.log('word length', wordsNeedingWork.length);


                // get all definitions from our database
                // when it calls back, draw the list
                bible.Storage.fillDefinitions(wordsNeedingWork, function(data) {

                    var wordList = data;
                    var showPartOfSpeech = $('#show-pos').attr('checked');
                    var showParsing = $('#show-parsing').attr('checked');
                    var showFrequency = $('#show-frequency').attr('checked');


                    var list = '';
                    for (var wi = 0; wi < wordList.length; wi++) {
                        var wordData = wordList[wi];

                        list += '<li>' + '<span class="' + ((bible.Reader.lang == 'G') ? 'gk' : 'hb') + '">' + wordData.lex + '</span>, ';

                        if ((showPartOfSpeech || (showParsing && wordData.posInfo != ''))) {
                            list += ' <span class="parsing-info">';
                            if (showPartOfSpeech && showParsing)
                                list += bible.Reader.getPartofSpeech(wordData.pos) + ((wordData.posInfo != '') ? ', ' + bible.Reader.getMorphology(wordData.pos, wordData.posInfo) : '');
                            else if (showPartOfSpeech && !showParsing)
                                list += bible.Reader.getPartofSpeech(wordData.pos);
                            else if (!showPartOfSpeech && showParsing)
                                list += bible.Reader.getMorphology(wordData.pos, wordData.posInfo);

                            list += '</span>, ';
                        }

                        list += '' + wordData.englishGlosses +
						((showFrequency) ? ' (' + wordData.tCount + '-' + wordData.bCount + ')' : '') +
						'</li>';
                    }

                    $('#footnotes').html('<ol>' + list + '</ol>');

                    // delete this info
                    wordList = null;
                    wordsNeedingWork = null;

                });
            }
        },

        updateStyles: function() {
            var styles = '';
            $('select.pos-rule').each(function(f) {
                var effect = $(this).val();
                if (effect != '') {
                    var ef = effect.substring(0, 1);
                    var css = '';
                    switch (ef) {
                        case 'h':
                            css = 'background-color: ' + effect.substring(2) + ';';
                            break;
                        case 'c':
                            css = 'color: ' + effect.substring(2) + ';';
                            break;
                        case 'b':
                            css = 'font-weight: bold;';
                            break;
                        case 'u':
                            css = 'text-decoration: underline;';
                            break;
                        case 'i':
                            css = 'font-style: italic;';
                            break;
                    }


                    styles += '.' + this.id + ' { ' + css + ' } ';
                }
            });

            try {
                $('#custom-styles').html(styles);
            } catch (ex) { }

        }
    }

    // STORAGE
    bible.Storage = {
        lexicon: null,

        init: function() {
            bible.Storage.settingsStore = new Persist.Store('settings');

            bible.Storage.lexiconStore = new Persist.Store('lexicon');

            // get lexicon
            bible.Storage.lexiconStore.get('lexicon', function(ok, data) {
                if (ok && data != null) {
                    bible.Storage.lexicon = []; //eval("(" + data + ")");
                } else {
                    bible.Storage.lexicon = [];
                }

                console.log('lexicon', ok, data);
            });
        },

        saveLexicon: function() {
            var x = jQuery.param(bible.Storage.lexicon)
            bible.Storage.lexiconStore.set('lexicon', x);
            console.log('lexicon store', bible.Storage.lexicon.length, bible.Storage.lexicon, x);
        },

        getLexicalEntry: function(sn, callback) {
            var entry = bible.Storage.lexicon[sn];

            if (entry != null) {
                callback(entry);
            } else {
                bible.Interface.getLexicalEntry(sn, function(data) {
                    // store
                    bible.Storage.lexicon[sn] = data;

                    // send				
                    callback(data);
                });
            }


        },

        getStrongs: function(word, callback) {
            // check store
            bible.Storage.strongsNumStore.get(word, function(ok, data) {
                // if in store, use it
                if (ok) {
                    callback(data);
                } else {
                    // else, pull it from ajax
                    bible.Interface.getStrongs(word, function(data) {
                        callback(data);
                    });
                }
            });
        },

        deleteRef: function() {
            bible.Storage.settingsStore.remove('reference', function(ok, data) { });
        },

        setRef: function(value) {
            bible.Storage.settingsStore.set('reference', value);
        },

        getRef: function(callback) {
            bible.Storage.settingsStore.get('reference', function(ok, data) { callback(ok, data); });
        },

        fillDefinitions: function(wordList, callback) {

            // (1) get the list of words not in the database
            var undefinedWords = [];
            for (var i = 0; i < wordList.length; i++) {

                var lex = wordList[i].lex;
                var strongsNum = wordList[i].strongsNum;
                var key = (lex != '') ? lex : strongsNum;

                var definition = bible.Storage.lexicon[key];
                if (!definition || definition == null)
                    undefinedWords.push(key);
            }

            console.log('word needing', undefinedWords.length, undefinedWords);

            // (4) fill the requested list
            function fillList() {
                // fill in this list
                for (var i = 0; i < wordList.length; i++) {

                    //var lex = wordList[i].lex;
                    var strongsNum = wordList[i].strongsNum;
                    var key = bible.Reader.lang + strongsNum; //(lex != '') ? lex : strongsNum;			

                    var definition = bible.Storage.lexicon[key];
                    console.log('looking', key, definition);

                    if (definition != null) {
                        wordList[i].englishGlosses = definition.KjvDefinition;
                        wordList[i].lex = definition.LexicalForm;
                    } else {
                        wordList[i].englishGlosses = '(not available)';
                        wordList[i].lex = '?';
                    }
                }

                // (5) run callback
                callback(wordList);
            }

            // (2) if we need words, get them via ajax
            if (undefinedWords.length > 0) {

                var wordQuery = undefinedWords.join(',');


                // grab all the words we need
                bible.Interface.getLexicalList(wordQuery, bible.Reader.lang, function(data) {

                    // (3) fill the database with the ajax words
                    for (var i = 0; i < data.length; i++) {
                        var definition = data[i];
                        var key = bible.Reader.lang + definition.StrongsNumber;
                        console.log('storing', key, definition);
                        bible.Storage.lexicon[key] = definition;
                    }

                    fillList();

                    // store for next time
                    bible.Storage.saveLexicon();

                });
            } else {
                fillList();
            }
        }
    };

    bible.Interface = {

        getLexicalList: function(words, lang, callback) {
						/*
            jQuery.get('get.ashx', { a: 'lexlist', d: words, l: lang }, function(data) {
                callback(data.list);
            }, 'json');
						*/
						
						jQuery.ajax({
							url: 'get.ashx', 
							type: 'GEt',
							data: { a: 'lexlist', d: words, l: lang }, 
							success: function(data) {
								console.log('request complete');
                callback(data.list);
							}, 
							error: function(req, status, error) {
								console.log('request error', req, status, error );
							}, 														
							dataType: 'json'
						});						
        },

        getLexicalEntry: function(word, callback) {

						jQuery.ajax({
							url: 'get.ashx', 
							type: 'GEt',
							data: { a: 'lex', d: word }, 
							success: function(data) {
								console.log('request complete');
                callback(data);
							}, 
							error: function(req, status, error) {
								console.log('request error', req, status, error );
							}, 														
							dataType: 'json'
						});			

						/*
            jQuery.get('get.ashx', { a: 'lex', d: word }, function(data) {
                callback(data);
            }, 'json');
						*/
        },

        getReference: function(reference, callback) {

						jQuery.ajax({
							url: 'get.ashx', 
							type: 'GEt',
							data: { a: 'ref', d: reference }, 
							success: function(data) {
								console.log('request complete');
                callback(data);
							}, 
							error: function(req, status, error) {
								console.log('request error', req, status, error );
							}, 							
							dataType: 'json'
						});			

						/*
            jQuery.get('get.ashx', { a: 'ref', d: reference }, function(data) {
                callback(data);
            }, 'json');
						*/
        }

    };

    bible.utils = {
        serializeJSON: function(a) {
            var s = '';

            // Serialize the key/values
            for (var j in a)
            // If the value is an array then the key names need to be repeated
                if (a[j] && a[j].constructor == Array)
                jQuery.each(a[j], function() {
                    s.push(encodeURIComponent(j) + "=" + encodeURIComponent(this));
                });
            else
                s.push(encodeURIComponent(j) + "=" + encodeURIComponent(jQuery.isFunction(a[j]) ? a[j]() : a[j]));

            // Return the resulting serialization
            return s.join("&").replace(/%20/g, "+");
        },

        deserializeJSON: function(s) {
            return eval("(" + s + ")");
        }
    }


    // START UP
    bible.Reader.init();
    bible.Storage.init();

    //  init refererence
    bible.Storage.getRef(function(ok, data) {

        var ref = (!ok || data == null || data.toString() == '' || data.toString().indexOf('Invalid') > -1) ? 'Rom 3:20-25' : data;
        $('#reference').val(ref);

        bible.Reader.getReference();

        // init styles	
        $('#pos-v').attr('selectedIndex', '2'); // verbs = red gb
        $('#pos-n').attr('selectedIndex', '7'); // nouns = green
        bible.Reader.updateStyles();

    });

});