/*
    name : historySuggest
    file : jquery.historySearch.js
    author : gregory tomlinson
    Dual licensed under the MIT and GPL licenses.
    ///////////////////////////
    ///////////////////////////        
    dependencies : jQuery 1.4.2, jquery.timeFormat.js, jquery.cookie.js, jquery.escapeHTML.js
    ///////////////////////////
    ///////////////////////////
    
*/

(function($) {
    
    $.fn.historySuggest = function( options ) {
        // extend the defaults settings
        var el = this, o = $.extend(true, defaults, options),
            searchBox, searchButton, searchContainer,
            clearSearch, searchLoading,
            originalTypedTerm = "", // remember this for later
            directToUrl = false,
            hiddenFocusField,
            historySuggestElementList,
            links = [],
            hintBox, position=-1, hintBoxOpen=false, punctuationRegex = new RegExp( "\\.", "gi" );
        
        if(el.length <= 0) return this;
        init();
        
        return this;
        
        function init() {
            el.bind('submit', validate);
            $bod = $(document.body);
            $bod.bind('blur', bodyBlur).click(bodyClickEvent);

            hintBox = createHintBox().insertAfter(el);
            //hiddenFocusField = $('<input type="text" name="" value="" class="historySuggestHiddenFormField" />').insertAfter(hintBox)
            //hiddenFocusField.bind('keyup', hintKeyPress)

            //$('html').bind('keypress', hintKeyPress)            
            //hintBox.bind('focus', hintFocus).click( hintBoxClickEvent );
            searchBox = el.find( o.searchBox );
            searchButton = el.find(o.searchButton).click(fullSearchEvent);
            searchBox.bind('focus', focus ).bind('blur', blur).bind('keyup', searchBoxKeyPress);     
            searchContainer = $(o.searchContainer);
            createControlIcons();
        }
        
        function createHintBox() {
            return $('<div id="hintBox" style="display:none;"></div>');
        }
        
        function createControlIcons() {
            searchLoading = $('<div class="historySuggestLoaderIconClass"></div>').appendTo( searchContainer );
        }
        
        //events 
        function focus(e) {}
        
        function hintFocus(e) {}
        
        function blur(e) {}
        
        function bodyBlur(e) {}
        
        function bodyClickEvent() {
            showHideBox(0);
        }
        
        function validate(e) {
            // look at the form - don't submit empty queries
            e.preventDefault();

            o.params.search_terms = searchBox.val();
            connector(o.url, o.params, success, error)
        }
        
        function fullSearchEvent(e) {
            
            /*
                Workflow Fork:
                    1. if the directToUrl check is true - go directly there
                    2. otherwise do 'real' search
            */            
            
            if( ! directToUrl ) {
                el.unbind('submit', validate);
                el.trigger('submit');                
            } else {
                document.location.href= directToUrl;
            }

        }
        
        function searchBoxKeyPress(e) {
            var lis = historySuggestElementList, search;
            console.log('searchBoxKeyPress', e.keyCode)
            
            if(e.keyCode === 40) {

                /*
                    In chrome, this is triggering, not te 'body' one!
                */
                console.log(this)
                //$(this).blur();
                // chrome hack?
                //
                //hiddenFocusField.focus();
                position++;                
                position = highlightSelectedItem( position );                
                
                
            } else if(e.keyCode === 38 ) {
                    // up arrow
                    e.preventDefault();
                    e.stopPropagation();

                    position--;
                    position = highlightSelectedItem( position );             

                    return false;                                

                } else if(e.keyCode === 13 ) {
                    // this is the enter KEY
                    console.log('position', position)
                    
                    if(position >=0 && position < lis.length) {
                        var li = lis.eq(position).find('a');
                        document.location = li.attr('href');                        
                        return;
                    } else {
                        searchButton.click();
                    }
                    
                    return;
                } else if(e.keyCode === 27) {
                    //escape key
                    showHideBox(0);
                } else {
                    search=searchBox.val();                    
                    originalTypedTerm = search;
                    // do a REGEX
                    if(search === '' ) {
                        hintBox.html('');
                        showHideBox(0);
                        return;
                    }
                    
                    //searchBox.addClass('historySuggestLoaderIconClass');

                    searchLoading.css('display', 'block');
                    o.params.regex = removePunctuation( search );
                    connector(o.url, o.params, success, error);
                }
            
        
            
                       
        }
        
        /*
            TODO:
                set a hidden field that says go directly to this link when they use the titles...
                
        */
        
 
        
        function hintBoxClickEvent(e) {
            
            var li = hintBox.find('li').eq(position).find('a');
            document.location = li.attr('href');
        }
        
        function highlightSelectedItem( pos ) {
            var lis = historySuggestElementList.removeClass('selected'),
                selected, originalLink, hashLink;
        
        
            console.log('pos', pos, searchBox)

            if(pos >= 0 && pos< lis.length) {
                
                
            } else {
                console.log('this is where the regular box is selected?', originalTypedTerm)
                if(pos >= lis.length) pos=-1;
                if(pos < 0 ) pos =-1;
                directToUrl = false; 
                searchBox.val( originalTypedTerm );  
                return pos;                
            }
        
            showHideBox(1);            
        
            selected = lis.eq(pos).addClass('selected');
            //originalLink = selected.find('.originalTitle').html();
            originalLink = (links[pos].title  &&  links[pos].title !== '') ? links[pos].title : links[pos].url
            hashLink = selected.find('.hashURL').html();
            searchBox.val( originalLink ); 
            directToUrl = hashLink;
            
            return pos;
        }
        
        
        function hintBoxHover(e) {

            var lis = hintBox.find('li').removeClass('selected'),
                pos = jQuery.inArray(this, lis),
                selected = lis.eq(pos).addClass('selected'),
                //link = selected.find('.originalTitle').html(),
                link = (links[pos].title  &&  links[pos].title !== '') ? links[pos].title : links[pos].url
                hashLink = selected.find('.hashURL').html();
        
            directToUrl = hashLink;
            searchBox.val( link );                
            position = pos;
        }
        
        function hintBoxUnhover(e) {
            
        }
        
        function removePunctuation( str ) {
            str = $.trim(str).replace(punctuationRegex, ' ');
            return str;
        }
        
        function error(e) {
            console.log('ERROR: unable to reach history suggest API', e)
        }
        
        // Remote Connection Success Method
        function success(jo) {
            // stick all the lis into an array and walk the array with a position?
            
            // calculate the height on the hint box after this is finished?
            if(!hintBoxOpen) position=-1;
            showHideBox(jo.data.results.length);
            var i=0, dedupe = {}, counter=0, html = "<ul>", title="",  
                s=searchBox.val(), search = new RegExp(s,"gi"),
                items = jo.data.results, displayTitle;
                
            links = items;
                
            for( ; i<items.length && counter < o.maxItems; i++) {
                if(dedupe[items[i]._id]) continue; // de dupe the result set from SERVER
                // TODO: this replace logic doesn't match the substitition after encoding on '<search' as a search
                title = trimToLength( $.escapeHTML(items[i].title), 94 ).replace(search, highLightWord);
                html += '<li position="'+i+'"><div>';
                    html += title;
                    html += '</div><div>';
                    html += '<a href="/'+items[i]._id+'+">' + prepareURL(search, $.escapeHTML(items[i].url), 84 ) + '</a>';
                    html += '</div><div class="suggestTimeItem">';
                    html += $.timeFormat( items[i].ts );
                    html += '</div><div style="display:none;" class="hashURL">'
                    html += '/' + items[i]._id + '+';
                html += '</div></li>';
                // add to list to dedupe the next time I see this URL
                dedupe[items[i]._id] = true;
                counter += 1;
            }
            html += '</ul>'
            hintBox.html( html );
            // TODO: don't do it this way
            // this has a LOT of potential for a memory leak... a very serious one.
            historySuggestElementList = hintBox.find('li');
            historySuggestElementList.hover( hintBoxHover, hintBoxUnhover ).filter(':last').addClass('lastHistorySuggestItem');
            //searchBox.removeClass('historySuggestLoaderIconClass');
            searchLoading.css('display', 'none');
        }
        
        
        // UTILS
        function highLightWord(word) {
            return '<b>' + word + '</b>'
        } 
        
        function showHideBox(length) {
            if(length > 0 ) { 
                hintBox.css('display', 'block');
                hintBoxOpen=true;
            } else { 
                hintBox.css('display', 'none');
                hintBoxOpen=false;
                //searchBox.removeClass('historySuggestLoaderIconClass');
                searchLoading.css('display', 'none');
            }
        }
        
        function prepareURL( search, url, length ) {
            var finalURL = "";
            finalURL = trimToLength( url, length ); // (url.length > length) ? url.substr(0, length-3) + "..." : url;
            
            return finalURL.replace(search, highLightWord)
        } 
        
        function trimToLength( str, length ) {
            if(!str) return "";
            return (str.length > length ) ? str.substr(0,length-3) + "..." : str;
        }      

    }
    
    
    var defaults = {
        url : '/data/suggest',
        params : {
            regex : ''
        },
        maxItems : 5,
        searchBox : '#historySearchInputTextField',
        searchContainer : '#mainSearchInputBox',
        searchButton : '#historySearchButton',
        txt : {
            search : ''
        }
    }, $bod, ajaxConnection;
    

    
    function connector(url, params, callback, error) {
        params._xsrf = $.cookie.get("_xsrf");
        var str = $.param( params );
        
        if(ajaxConnection) ajaxConnection.abort();
        
        ajaxConnection = $.ajax({
            dataType: 'json',
            data : str,
            type : 'POST',
            'url' : url,
            success: callback,
            'error' : error            
        });
        
    }

})(jQuery);
