(function($){
    $.extend($.expr[':'],{
        customDropDownSelected: function(a) {
            return $(a).hasClass('selected');
        }
    });

    $.createCustomDropDownMenuItem = function(containerAttributes, itemText, itemAttributes) {
        var linkHtml = '<a';

        $.each(itemAttributes, function(key, value){
            linkHtml += ' ' + key + '="' + value + '"';
        });

        linkHtml += '>' + itemText + '</a>';

        var containerAttributesString = '';

        $.each(containerAttributes, function(key, value){
            containerAttributesString += ' ' + key + '="';

            if(key == 'class') {
                containerAttributesString += 'menuItem ';
            }

            containerAttributesString += value + '"';
        });

        return $('<li ' + containerAttributesString + '>' + linkHtml + '</li>');
    }

    /**
     * Used to create a custom drop down menu.
     */
    $.fn.customDropDown = function() {
        var SELECTED_GROUP_MENU_ITEM_CLASS = 'groupSelected';

        this.each(function() {
            var myMenu = $(this);

            //Get all submenu objs
            var menuGroupObjs = myMenu.find('li.menuItemGroup');

            //stores whether or not the mouse is over the custom drop down
            var isMouseOverDropDown = false;

            //stores whether or not a clicked menu item should close the menu
            var shouldMenuPersist = false;

            //the object that contains the currently selected menu item's text
            var selectedMenuItemTextObj = myMenu.find('span.selectedOptionSpan');

            //the container that contains all the menu items
            var menuItemContainerObj = myMenu.find('ul.menuItemContainer');

            //the container that holds the drop down menu's selected item image, text and drop down arrow
            var customDropDownHeaderObj = myMenu.find('a.customDropDownHeader');

            var customDropDownArrowContainerObj = customDropDownHeaderObj.find('span.selectArrowContainer');

            //console.profile('select text');
            var currentlySelectedMenuItemObj = myMenu.find('li.selected');
            //console.profile('select text');
            
            var currentlySelectedMenuItemImageObj = $('img.selectedMenuItemImage', customDropDownHeaderObj);

            //True if the mouse cursor is over the drop down menu
            var isMouseOverSubMenu = false;

            //initialize the default selected menu item
            if(currentlySelectedMenuItemObj.length == 0){
                currentlySelectedMenuItemObj = myMenu.find('li.menuItem:first');
            }

            else if(currentlySelectedMenuItemObj.length >= 1){
                currentlySelectedMenuItemObj = currentlySelectedMenuItemObj.first();
            }

            //set the selected group menu item for each group
            menuGroupObjs.each(function(){
                var currentSelectedGroupMenuItemObj = $('li.menuItem.groupSelected', $(this));

                if(currentSelectedGroupMenuItemObj.length == 0) {
                    $(this).data('groupSelectedObj', $('li.menuItem:first', $(this)));
                }

                else {
                    $(this).data('groupSelectedObj', currentSelectedGroupMenuItemObj);
                }
            });

            myMenu.mouseenter(function(){
                isMouseOverDropDown = true;
            });

            myMenu.mouseleave(function(){
                isMouseOverDropDown = false;
                isMouseOverSubMenu = false;
                shouldMenuPersist = false;
            });

            //fired when the custom dropdown header is clicked
            $('a.customDropDownHeader', myMenu).click(function(){

                menuItemContainerObj.toggle();

                //console.log(menuItemContainerObj.width() + ' | ' + customDropDownArrowContainerObj.width());

                //reset variables
                shouldMenuPersist = false;

                return false;
            });

            //when the custom menu loses focus close it
            myMenu.bind('focusout', function(){
                if(!isMouseOverDropDown){
                    menuItemContainerObj.hide();
                }
            });

            //Show the menu images only once they are loaded fully
            currentlySelectedMenuItemImageObj.load(function(){
               if($(this).attr('src')){
                   $(this).show();
               }

               else{
                   $(this).hide();
               }
            });

            myMenu.change(function(event, menuItemObj){
                if(!$.isEmptyObject(menuItemObj)){
                    //change the selected menu item
                    currentlySelectedMenuItemObj.removeClass('selected');
                    menuItemObj.addClass('selected');
                    currentlySelectedMenuItemObj = menuItemObj;

                    //change selected menu item text
                    selectedMenuItemTextObj.text(menuItemObj.text());
                    selectedMenuItemTextObj.attr('title', menuItemObj.text());
                    
                    var associatedImageSrc = menuItemObj.css('background-image');

                    currentlySelectedMenuItemImageObj.hide();

                    //format the url to the icon image for the selected option
                    if(associatedImageSrc!='none'){
                        associatedImageSrc = associatedImageSrc.substring(5, associatedImageSrc.length-2);
                    }

                    else{
                        associatedImageSrc = '';
                    }

                    // Check if there's an image first
                    if (currentlySelectedMenuItemImageObj != undefined){
                        // Change the image
                        currentlySelectedMenuItemImageObj.attr("src", associatedImageSrc);
                    }
                }
                //copy the text of the selected menu item into the menu header
                else{
                    selectedMenuItemTextObj.text($('li.selected', myMenu).text());
                    selectedMenuItemTextObj.attr('title', $('li.selected', myMenu).text());
                }

                //reset variables
                shouldMenuPersist = false;
            });

            //make menu items do nothing if they are disabled
            $('li.menuItem', myMenu).bind('click', function(){
                if($(this).hasClass('disabled')){
                    return false;
                }
            });

            //handle the clicking of a menu item
            $('li.menuItem', myMenu).live('click', function(){
                if($(this).hasClass('persist')){
                    shouldMenuPersist = true;
                }

                else {
                    //hide the main menu
                    menuItemContainerObj.hide();

                    //hide all submenus
                    $('li.subMenuItem ul.subMenuItemContainer', myMenu).hide();
                }

                //if the menu item is selectable
                if(!$(this).hasClass('dontSelect')){
                    myMenu.trigger('change', [$(this)]);
                }

                //if the menu item is group item selectable
                if(!$(this).hasClass('dontGroupSelect')){
                    var parentMenuItemGroupObj = $(this).parentsUntil('li.menuItemGroup').parent();

                    if(parentMenuItemGroupObj.data('groupSelectedObj') != undefined && parentMenuItemGroupObj.data('groupSelectedObj').length != 0) {
                        parentMenuItemGroupObj.data('groupSelectedObj').removeClass(SELECTED_GROUP_MENU_ITEM_CLASS);
                    }

                    parentMenuItemGroupObj.data('groupSelectedObj', $(this));
                    $(this).addClass(SELECTED_GROUP_MENU_ITEM_CLASS);
                }
            });

            //show or hide the submenu if you click onn the submenu item
            $('li.subMenuItem', myMenu).live('click', function(event){
                //this check is made so if the click event is fired programatically
                //then it will not make the sub menu show up next time the menu is opened
                if(menuItemContainerObj.is(':visible')){
                    $('.subMenuItemContainer', $(this)).toggle();
                }
            });

            $('li.subMenuItem', myMenu).live('mouseenter', function(){
                isMouseOverSubMenu = true;
            });

            $('li.subMenuItem', myMenu).live('mouseleave', function(){
                isMouseOverSubMenu = false;
            });

            //hide sub menus when they lose focus
            $('li.subMenuItem', myMenu).live('blur', function(){
                if(!isMouseOverSubMenu) {
                    $('.subMenuItemContainer', $(this)).hide();
                }
            });
            
            //force the selection of the menuItem with class selected
            currentlySelectedMenuItemObj.trigger('click');

            //if the menu has the class sizeToContent it will set the width of the custom drop down to the width of the longest menuItem + arrow space
            if(myMenu.hasClass('sizeToContent'))
            {
                myMenu.width(menuItemContainerObj.width() + customDropDownArrowContainerObj.width()) ;
            }
        });

        return this;
    };

})(jQuery);
