String.prototype.ltrim = function () { return this.replace(/^\s+/, ''); };
String.prototype.rtrim = function () { return this.replace(/\s+$/, ''); };
String.prototype.trim  = function () { return this.replace(/^\s+|\s+$/g, ''); };

var _debug_states = [];

$.fn.extend({
    disable: function () {
        return this.each(function () {
            $(this).attr('disabled', 'disabled');
        });
    },
    enable: function () {
        return this.each(function () {
            $(this).removeAttr('disabled');
        })
    }
});

$(function () {
    // Restaurant options elements
    var opts = $( 'select#restaurant option' ).filter(function () {
        // Do not include the generic "select a restaurant" in the selected elts
        return ( $(this).text().substring( 0, 2 ) !== '--' );
    }).each(function () {
        $(this).attr( 'state', $(this).text().substring( $(this).text().length - 2 ) );
    });

    var rsSel = $( 'select#restaurant' );

    var stSel = $( 'select#state' );
    
    var optsArr = opts.map(function () {
        return $(this).text();
    });

    var stSel_onChange = (function () {
        var hideOpts, showByState;

        /**
         * Mozilla can handle hide()-ing and show()-ing <option/> elements
         * and it's much faster, so if this is mozilla, use the hide/show.
         * Otherwise, use the remove/append method.
         */
        if ($.browser.mozilla) {
            hideOpts = function( obj ) {
                opts.hide();
            };
            showByState = function ( obj, state ) {
                hideOpts( obj );
                getOptsByState( state ).show();
            };
        } else {
            hideOpts = function ( obj ) {
                obj.html( '' );
            };
            showByState = function ( obj, state ) {
                hideOpts( obj );
                obj.append( getOptsByState( state ) );
            }
        }

        var getOptsByState = function ( state ) {
            return opts.filter( '[state=' + state + ']' );
        };

        return function () {
            var $this = $(this);
            var state = $this.val();

            // If a state is selected (i.e., the value is not null)
            if ( state ) {
                // Remove all existing options and append appropriate options
                showByState( rsSel, state );
                rsSel.enable();
            } else {
                // If there is no state selected, remove all elements
                hideOpts( rsSel );
                rsSel.disable();
            }
        };
    }());

    var autocompleteOptions = {
        max:        10,
        mustMatch:  0
    };

    var ac = $( '#restaurant-name' ).enable().autocomplete( optsArr, autocompleteOptions );

    stSel.change(stSel_onChange).trigger('change');

    
    stSel.children('option').each(function () {
        var val = $(this).val();
        
        // Remove states that have no associate restaurants
        if ( val ) {
            var filterExpr = '[state=' + val + ']';
            _debug_states.push(filterExpr);
            if ( opts.filter( filterExpr ).length === 0 ) {
                $(this).remove();
            }
        }
    });
    


    $('#submit-search').click(function ( evt ) {
        // Prevent the submit button from actually submitting
        evt.preventDefault();

        // Function to redirect user to details page
        var redirect = function ( id ) {
            window.location = '/details/' + id + '.html';
        };

        // Function to send an error to the user if no store is selected
        var errorToUser = function () {
            alert( 'Please select a restaurant from the drop down list or search for one in the search box.' );
        };


        // Try the search text first
        var searchText = $( '#restaurant-name' ).val();
        if ( searchText ) {
            // find options where the text matches the search text
            var matchingOpt = opts.filter(function () {
                return ( $(this).text() === searchText );
            });

            // If the length is not zero
            if ( matchingOpt.length ) {
                // redirect the user with the value of the first matched opt
                redirect( matchingOpt.val() );
                return;
            }
        }

        // Try the select box next
        var rsOptVal = rsSel.val();
        // If there is a value selected
        if ( rsOptVal ) {
            // Redirect the user to that value
            redirect( rsOptVal );
            return
        }

        // No match found
        errorToUser();
    });
});