(function($){
    $.fn.dropDownMenu = function(options) {
        var settings = $.extend({}, $.fn.dropDownMenu.defaults, options);

        return this.each(function() {
            $.dropDownMenu(this, settings);
        });
    };

    $.dropDownMenu = function (element, settings) {
        var e = $(element)[0];
        return e.dropDownMenu || (e.dropDownMenu = new jQuery._dropDownMenu(e, settings));
    };

    $._dropDownMenu = function(element, settings) {
        $(element).addClass('dropdownmenu');

        $(element).find('ul').parent().hover(
            function(e) {
                $(this).children('a:eq(0)').addClass('selected');
            },
            function(e){
                $(this).children('a:eq(0)').removeClass('selected');
            }
        );
        
        $(element).find('ul').parent().each(function(i) {
            currentElement = $(this);
            $(currentElement).css({ zIndex: 100 - i });

            var subElements = $(this).find('ul:eq(0)');
            $(subElements).css({ display:'block' });
            $(subElements).data('timers', {});

            this._dimensions = {
                w: this.offsetWidth,
                h:this.offsetHeight,
                subUlWidth: $(subElements).outerWidth(),
                subUlHeight: $(subElements).outerHeight()
            };

            this.isTopHeader = $(this).parents('ul').length == 1 ? true : false;
            $(subElements).css({ top: this.isTopHeader ? this._dimensions.h + 'px' : 0 });

            $(currentElement).hover(
                function(e) {
                    var targetUl = $(subElements);
                    var header = $(e.currentTarget).get(0);

                    clearTimeout(targetUl.data('timers').hidetimer);

                    targetUl.data('timers').showtimer = setTimeout(function() {
                        header._offsets = { left: $(e.currentTarget).offset().left, top: $(e.currentTarget).offset().top };

                        var menuleft = header.isTopHeader ? 0 : header._dimensions.w;

                        menuleft = (header._offsets.left + menuleft + header._dimensions.subUlWidth > $(window).width()) ? (header.isTopHeader ? -header._dimensions.subUlWidth + header._dimensions.w : -header._dimensions.w) : menuleft;
                        if (targetUl.queue().length <= 1) {
                            targetUl.css({ left: menuleft + 'px', width: header._dimensions.subUlWidth + 'px' }).animate({ height: 'show', opacity: 'show' }, 300) // transitionOverTime
                        }
                    }, 10); // showDelay
                },
                function(e) {
                    var targetUl = $(subElements);
                    var header = $(e.currentTarget).get(0);

                    clearTimeout(targetUl.data('timers').showtimer);

                    targetUl.data('timers').hidetimer = setTimeout(function() {
                        targetUl.animate({ height: 'hide', opacity: 'hide' }, 300); // transitionOutTime
                    }, 200); // hideDelay
                }
            );
        });

        $(element).find('ul').css({ display:'none', visibility:'visible' });
    };

    $.fn.dropDownMenu.defaults = {
        transitionOverTime: 300,
        transitionOutTime: 300,
        showDelay: 100,
        hideDelay: 200
    };
})(jQuery);
