(function($){
    $.fn.animateMenu = function(args){
        var am = this;
        var amTimer = null;
        var amDefaultParams = {
            hoverClass: 'am-hover',
            selectedClass: 'am-selected',
            openClass: 'am-open',
            delay: 3000,
            animation: {
                opacity: 'show',
                width: 'show'
            },
            speed: 800,
            type: 'innerClick'
        };
        var amParams = $.extend(amDefaultParams, args);
        
        var outerOver = function(event){
            if (amTimer) {
                clearTimeout(amTimer);
            }
            if (event.target != $(this).get(0) && event.target.nodeName != 'UL') {
                var $amCurrentLI;
                if (event.target.nodeName != 'LI') {
                    $amCurrentLI = $(event.target).closest('li');
                }
                else {
                    $amCurrentLI = $(event.target);
                }
                var $amChildrenUL = $('ul:first', $amCurrentLI).stop();
                if ($amChildrenUL.length) {
                    if (amParams.type != 'outerTopHover' || $(this).get(0) != $amCurrentLI.parent().get(0)) {
                        $amChildrenUL.amBuildOuterLeft();
                    }
                    $amChildrenUL.amClearCSS();
                }
                $(am).find('ul').not($amCurrentLI.parents('ul')).not($amChildrenUL).stop().hide();
            }
        };
        
        var outerOut = function(event){
            if (amTimer) {
                clearTimeout(amTimer);
            }
            amTimer = setTimeout(function(){
                $(am).find('ul').stop().hide();
            }, amParams.delay);
        };
        
        var innerClick = function(){
            if ($('ul:first', this).is(':visible')) {
                $('ul:first', this).stop().hide().closest('li').removeClass(amParams.openClass);
            }
            else {
                var $amChildrenUL = $('ul:first', this).stop();
                if ($amChildrenUL.length) {
                    $amChildrenUL.amClearCSS();
                    $amChildrenUL.closest('li').addClass(amParams.openClass);
                }
            }
        };
        
        var innerOver = function(event){
            var $amChildrenULs = (am).find('ul:animated').stop();
            if ($amChildrenULs.length) {
                $amChildrenULs.amClearCSS();
            }
            if (event.target != $(this).get(0) && event.target.nodeName != 'UL') {
                var $amCurrentLI;
                if (event.target.nodeName != 'LI') {
                    $amCurrentLI = $(event.target).closest('li');
                }
                else {
                    $amCurrentLI = $(event.target);
                }
                var $amChildrenUL = $('ul:first', $amCurrentLI).stop().closest('li').removeClass(amParams.openClass);
                if ($amChildrenUL.length) {
                    $amChildrenUL.amClearCSS();
                    $amChildrenUL.closest('li').addClass(amParams.openClass);
                }
            }
        };
        
        var innerOut = function(){
            $(am).find('ul').stop().fadeOut(amParams.delay);
        };
        
        $.fn.extend({
            animateMenuBind: function(){
                switch (amParams.type) {
                    case 'innerClick':
                        $('li:has(ul)', this).click(innerClick);
                        $('li', this).click(function(event){
                            event.stopPropagation();
                        });
                        break;
                    case 'innerHover':
                        $(this).mouseover(innerOver);
                        $(this).mouseout(innerOut);
                        break;
                    case 'outerTopHover':
                        $('li:has(ul)', this).amBuildOuterTop();
                    case 'outerLeftHover':
                        $('li:has(ul)', this).amBuildPosition();
                        $(this).mouseover(outerOver);
                        $(this).mouseout(outerOut);
                        break;
                    default:
                        alert('Неверно указан тип меню!');
                }
            },
            
            amBuildOuterLeft: function(){
                if ($.browser.msie && $.browser.version < 7) {
                    $(this).css({
                        left: $(this).closest('ul').outerWidth() - ($(this).closest('ul').outerWidth() - $(this).closest('li').width()) / 2
                    });
                }
                else {
                    $(this).css({
                        left: $(this).closest('ul').outerWidth() - ($(this).closest('ul').outerWidth() - $(this).closest('li').innerWidth()) / 2
                    });
                }
                if ($.browser.msie) {
                    if ($.browser.version < 7) {
                        $(this).css({
                            top: 2
                        });
                    }
                    else {
                        $(this).css({
                            top: 2 - ($(this).closest('li').outerHeight() - $(this).closest('li').innerHeight()) / 2
                        });
                    }
                }
                else {
                    $(this).css({
                        top: 0 - ($(this).closest('li').outerHeight() - $(this).closest('li').innerHeight()) / 2
                    });
                }
            },
            
            amBuildOuterTop: function(){
                $(this).find('ul').css({
                    left: -($(this).outerWidth() - $(this).innerWidth()) / 2,
                    top: ($(this).outerHeight() - $(this).innerHeight()) / 2 + $(this).innerHeight()
                });
            },
            
            amBuildPosition: function(){
                $(this).css('position', 'relative').find('ul').css('position', 'absolute');
            },
            
            amClearCSS: function(){
                var $currentThis = $(this);
                $.each(amParams.animation, function(i){
                    $currentThis.css(i, '');
                    $currentThis.css('overflow', '');
                });
                $currentThis.animate(amParams.animation, amParams.speed);
            }
        });
        
        return this.each(function(){
            $('li', this).hover(function(){
                $(this).addClass(amParams.hoverClass);
            }, function(){
                $(this).removeClass(amParams.hoverClass);
            });
            $('li:has(ul)', this).addClass('am-arrow');
            $(this).animateMenuBind();
            if (amParams.type.substr(0, 5) == 'inner') {
                $('.' + amParams.selectedClass, this).children('ul').show().parents('li').addClass(amParams.selectedClass).parent().show();
            }
        });
    };
})(jQuery)
