$(function() {

    // Milliseconds to wait before performing a search after pressing a key
    var SEARCH_TIMEOUT = 200;

    // URL from which we request our search results via AJAX
    var SEARCH_URL = '/titles/';

    // Elements
    var $searchField = $('#f-titles-search');
    var $paging = $('.titles-pagi');
    var $pagingInput = $paging.find('input');
    var $noResults = $('.titles-search-noresults');
    var $listViewHeaders = $('.search-list-view-headers');
    var $listGridButton = $('.btn-search-view');
    var $resultCount = $('#search-result-count');

    // Miscellaneous variables
    var pageType;
    var searchFieldDefaultValue = 'Begin typing…';
    var lastResponse;
    var initialLoad = true;
    var cursor = 1; // page number
    var timeoutId;

    // HTML templates for search results
    var templates = {
        categoryHeader:
            '<li class="search-hd">\
                <h2>{TITLE}</h2>\
            </li>',
        list:
            '<li>\
                <span class="item-name"><a href="{URL}"><b>{TITLE}</b></a>{EDITION} Edition</span>\
                <span>{AUTHOR}</span>\
                <span class="item-isbn">ISBN-10: {ISBN10}<br />ISBN-13: {ISBN13}</span>\
                <span class="item-pub">{PUBLISHER}</span>\
            </li>',
        grid:
            '<li>\
                <a href="{URL}" class="title-thumb"><img src="{IMG}" width="180" height="229" align="top" alt="" /></a>\
                <h4><a href="{URL}">{TITLE}</a></h4>\
                {EDITION} Edition<br />\
                {AUTHOR}<br />\
                ISBN-10: {ISBN10}<br />\
                ISBN-13: {ISBN13}<br />\
                {PUBLISHER}\
            </li>'
    };

    // Determine if we're looking at the list or grid view
    if($listGridButton.hasClass('btn-grid')) {
        pageType = 'grid';
    } else {
        pageType = 'list';
    }

    // Load initial resultset
    if(typeof titles_json != 'undefined') {
        renderResults(titles_json);
    }

    // Set search field default value
    $searchField.val(searchFieldDefaultValue);


    // Bindings for the search field element
    $searchField.bind({
       focus: function(e) {
           if($(this).val() == searchFieldDefaultValue) {
               $(this).val('');
           }
       },
       blur: function(e) {
           if($(this).val() == '') {
               $(this).val(searchFieldDefaultValue);
           }
       },
       keyup: function(e) {
           if(e.keyCode == '13') {
               // Don't submit the form if a user presses return or enter
               e.preventDefault();
               return false;
           }

           clearTimeout(timeoutId);

           timeoutId = setTimeout(function() {
               var cursor = 1; // reset page numbering if we're doing a new search
               performSearch();
           }, SEARCH_TIMEOUT);
       }
    });


    // Bindings for the paging input element
    $pagingInput.bind({
        keyup: function(e) {

            // Return/enter key jumps to page
            if(e.keyCode == '13' && $(this).val()) {
                e.preventDefault();

                cursor = $(this).val();
                performSearch();

                return false;
            }

            var newVal = '';
            var chars = $(this).val().split('');

            // Remove non-numerals
            for(var i = 0; i < chars.length; i++) {
                if(!isNaN(parseInt(chars[i], 10))) {
                    newVal += chars[i];
                }
            }

            $(this).val(newVal);
        }
    });


    // Bindings for paging buttons
    $paging.find('.pagi-l, .pagi-r').click(function() {

        if($(this).hasClass('pagi-l')) {
            cursor--;
        } else {
            cursor++;
        }

        performSearch();

        return false;
    });


    // Bindings for list/grid toggling button
    $listGridButton.click(function(e) {
        if($(this).hasClass('btn-grid')) {
            $(this).removeClass('btn-grid');
            pageType = 'list'
        } else {
            $(this).addClass('btn-grid');
            pageType = 'grid'
        }

        renderResults();

        return false;
    });


    // Submit a search request via AJAX
    function performSearch() {

        var queryString = '';

        if($searchField.val() != searchFieldDefaultValue) {
            queryString = 'q=' + escape($searchField.val()) + '&';
        }

        $.get(SEARCH_URL + '?' + queryString + 'cursor=' + cursor, renderResults);
    }


    // Draw search results on the page. This is either invoked after a
    // successful AJAX request after text has been entered into the search
    // field or when the user switches between list and grid views. In the
    // latter case, we simple call this function with no arguments.
    function renderResults(response) {
        
        if(typeof response != 'object') {
            response = eval('(' + response + ')');
        }

        if(response) lastResponse = response;
        else response = lastResponse;

        cursor = response.currentPage;

        // Remove existing search results
        flushSearchResults();

        // Display the number of results
        $resultCount.text(response.totalResults + ' Title');
        if(response.totalResults != 1) $resultCount.text($resultCount.text() + 's');

        // No search results
        if(response.totalResults == 0) {
            $('.search-list-view, .search-grid-view').remove();
            $paging.hide();
            $noResults.show();
            return;
        } else {
            $noResults.hide();
        }

        // Iterate over categories
        $.each(response.results, function(key, value) {

            var $resultsContainer;

            if(pageType == 'list') {
                $resultsContainer = $('<ul class="search-list-view"></ul>');
            } else {
                $resultsContainer = $('<div class="search-grid-view"><ul></ul></div>');
            }

            // Insert cateogry header
            $(templates.categoryHeader.replace('{TITLE}', key)).appendTo( pageType == 'grid' ? $resultsContainer.find('ul') : $resultsContainer );

            // Iterate over categories' contents
            $.each(value, function(key, value) {
                var markup = templates[pageType]
                    .replace(/\{URL\}/gm, value.url)
                    .replace('{TITLE}', value.title)
                    .replace('{EDITION}', value.edition)
                    .replace('{AUTHOR}', value.author)
                    .replace('{ISBN10}', value.isbn10)
                    .replace('{ISBN13}', value.isbn13)
                    .replace('{PUBLISHER}', value.publisher_name)
                    .replace('{IMG}', value.img);

                var $markup = $(markup);

                // If URL field is empty then strip out link tags and
                // add a 'coming soon' image
                if(value.url == '') {
                    $markup.find('b').unwrap();
                    $markup.find('img').unwrap();
                    $markup.find('img').wrap('<span class="title-thumb">');
                    $markup.find('h4').text( $markup.find('h4>a').detach().text() );
                    $markup.find('span.title-thumb').append('<img class="coming-soon" src="/_img/generic/coming-soon.png" width="130" height="131" alt="Coming Soon" />');
                    $markup.find('span.item-name>b').append('<i>Coming Soon</i>');
                }

                // Insert result items
                if(pageType == 'list') {
                    $markup.appendTo($resultsContainer);
                } else {
                    $markup.appendTo($resultsContainer.find('ul'));
                }

            });

            $resultsContainer.insertBefore($paging);
        
            // If we're in grid view normalize elements' heights so floats don't break
            $('.search-grid-view').each(function() {
                var maxHeight = 0;

                $(this).find('li[class!="search-hd"]').each(function() {
                    if($(this).height() > maxHeight) maxHeight = $(this).height();
                }).height(maxHeight);
            });

        });

        // Set paging info
        $paging.find('input').val(response.currentPage);
        $paging.find('b').text(response.totalPages);

        // Determine if we should hide the paging back button
        if(response.currentPage == 1) {
            $paging.find('.pagi-l').css('visibility', 'hidden');
        } else {
            $paging.find('.pagi-l').css('visibility', 'visible');
        }

        // Determine if we should hide the paging forward button
        if(response.currentPage == response.totalPages) {
            $paging.find('.pagi-r').css('visibility', 'hidden');
        } else {
            $paging.find('.pagi-r').css('visibility', 'visible');
        }

        // Or should we just hide all the paging altogether?
        if(response.totalPages == 1) {
            $paging.hide();
        } else {
            $paging.show();
        }
    }


    function flushSearchResults() {
        
        var $listViewHeaders = $('.search-list-view-headers');
        
        $('.search-list-view, .search-grid-view').each(function(i) {
            if(!$(this).hasClass('search-list-view-headers')) {
                $(this).remove();
            }
        });
        
        pageType == 'list' ? $listViewHeaders.show() : $listViewHeaders.hide();
    }


});

