/***
**  JQUERY MINIMENU PLUGIN
**	WRITTEN BY TOM ROMBAUT
**  Version 0.1
**  11/2009
**  DEPENDENCIES : JQUERY 1.3.1+ , JQUERY UI 1.7.2+
***/
var MiniMenu = function (options) {
    var conf = $.extend({}, $.fn.minimenu.defaults, options);
    var menu = $("<div class='minimenu'></div>");
    var status = "hidden";
    var pos = {};
    var loaded = false;
    var children = new Array();
    var cached = false;
    var timeout = false;
    var parent = false;
    var data = false;
    var menuItems = new Array();
    var intervalID = false;
    var ulheight = 0;
    var liheight = 0;

    var _initialize = function () {
        if (conf.data) {
            data = conf.data;
        }
        if (conf.classname)
            menu.addClass(conf.classname);

        if (conf.showIcon)
            menu.addClass(conf.hasiconclass);

        if (conf.preload) {
            _load(false);
        }
    };

    /** 
    ***LOAD DATA
    **/

    var _load = function (show) {
        if (data) {
            loaded = true;
            _createMenuItems(data);
            if (show) {
                _show();
            }
        } else {
            $.ajax({
                type: conf.method,
                url: conf.url,
                data: conf.params,
                dataType: conf.datatype,
                success: function (data) {
                    _createMenuItems(data);
                    if (show) {
                        loaded = true;
                        _show();
                    }
                }
            });
        }
    };
    /** 
    **	CREATE MENU ITEMS 
    **/
    var _createMenuItems = function (data) {
        menu.append($("<ul></ul>"));

        for (i = 0; i < data.length; i++) {
            if (data[i].separator)
                $("ul", menu).append($('<li class="mm-separator"></li>'));


            var menuItem = new MiniMenuItem(data[i], conf, menu);
            $("ul", menu).append(menuItem);
            menuItems[menuItems.length] = menuItem;

        }
        _createEvents();
        if (conf.oddclass) {
            for (i = 0; i < menuItems.length; i++) {
                if (i % 2 == 0) {
                    menuItems[i].addClass(conf.oddclass);
                }
            }
        }
        if (conf.evenclass) {
            for (i = 0; i < menuItems.length; i++) {
                if (i % 2 == 1) {
                    menuItems[i].addClass(conf.evenclass);
                }
            }
        }


        $('body').append(menu);
        if (conf.width == "auto") {
            if ($.browser.msie && $.browser.version < 8) {
                for (i = 0; i < menuItems.length; i++) {
                    menuItems[i].css("width", menu.width());
                }
            }
        } else {
            menu.css("width", conf.width);
        }

        if (conf.maxitems && conf.maxitems < menuItems.length) {
            liheight = 0;
            ulheight = 0;

            for (i = 0; i < conf.maxitems; i++) {
                liheight += menuItems[i].outerHeight();
            }
            for (i = 0; i < menuItems.length; i++) {
                ulheight += menuItems[i].outerHeight();
            }
            $("ul", menu).css({
                height: liheight,
                overflow: "hidden",
                padding: 0
            });
            _initscrolling();

        }

    };
    /** 
    **	CREATE REGULAR EVENTS
    **/
    var _createEvents = function () {
        $("li", menu).mouseover(function () {
            //menu.hideChildren();
        });
        menu.hover(function () {
            menu.clearHideTimer();
        }, function () {
            menu.setHideTimer();
        });
    };

    /** SHOW MENU **/
    var _show = function () {
        if (status == "hidden") {
            if (loaded) {
                menu.css({ left: pos.x, top: pos.y });
                menu.css("visibility", "visible");
                status = "shown";
                if ($.isFunction(conf.onshow)) {
                    conf.onshow(menu);
                }
            } else {
                _load(true);
            }
        }
    };
    /** HIDE MENU **/
    var _hide = function (all) {
        if (status == "shown") {
            menu.hideChildren();
            if (all && parent)
                parent.hide(true);

            menu.css("visibility", "hidden");
            status = "hidden";
            if ($.isFunction(conf.onhide)) {
                conf.onhide(menu);
            }
        }
    };
    var _initscrolling = function () {
        menu.prepend($("<div class='mm-scroller mm-s-up'></div>"));
        menu.append($("<div class='mm-scroller mm-s-down'></div>"));
        $(".mm-s-up", menu).mouseover(function () {
            _startscrolling("up");
        });
        $(".mm-s-up", menu).mouseout(function () {
            _endscrolling("up");
        });
        $(".mm-s-down", menu).mouseover(function () {
            _startscrolling("down");
        });
        $(".mm-s-down", menu).mouseout(function () {
            _endscrolling("down");
        });
        _checkscrollers();
    };
    var _startscrolling = function (type) {
        if (!intervalID) {
            intervalID = setInterval(function () { _scroll(type) }, conf.scrollinterval);
        }
    };
    var _endscrolling = function (type) {
        if (intervalID) {
            clearInterval(intervalID);
            intervalID = false;
        }
    };
    var _scroll = function (type) {
        var diff = $("ul li:first", menu).height();

        if (type == "up") {
            $("ul li:first", menu).animate({ marginTop: (_getmargin() + diff) + "px" }, 100, function () { _checkscrollers(); });
        } else if (type == "down") {
            $("ul li:first", menu).animate({ marginTop: (_getmargin() - diff) + "px" }, 100, function () { _checkscrollers(); });
        }
        _checkscrollers();
    };
    var _checkscrollers = function () {
        if (_getmargin() >= 0) {
            if ($(".mm-s-up", menu).css("display") != "none") {
                _endscrolling();
                $(".mm-s-up", menu).css("display", "none");
            }
        } else {
            $(".mm-s-up", menu).css("display", "block");
        }
        if (Math.abs(_getmargin()) >= (Math.abs(ulheight) - liheight)) {
            if ($(".mm-s-down", menu).css("display") != "none") {
                $(".mm-s-down", menu).css("display", "none");
                _endscrolling();
            }
        } else {
            $(".mm-s-down", menu).css("display", "block");
        }
    }
    var _getmargin = function () {
        return ($("ul li:first", menu).css("marginTop").replace("px", "") * 1);
    };

    /** PUBLIC METHOD **/
    menu.getStatus = function () {
        return status;
    };
    menu.hide = function (all) {
        _endscrolling();
        _hide(all);
    };
    menu.hideChildren = function () {
        /*for(key in children){
        if(children[key].getStatus() == "shown"){
        children[key].hide();
        }
        }*/
        for (var i = 0; i < menuItems.length; i++) {
            menuItems[i].hideChild();
        }
    }
    menu.show = function () {
        _show();
    };
    menu.setPosition = function (position) {
        pos = position;
    };
    menu.getPosition = function () {
        return pos;
    };
    menu.clearHideTimer = function () {
        if (timeout) {
            clearTimeout(timeout);
            timeout = false;
        }
        if (parent) {
            parent.clearHideTimer();
        }

    };
    menu.setHideTimer = function () {
        if (!timeout) {
            timeout = setTimeout(function () { menu.hide(); }, conf.timeToHide);
        }
        if (parent) {
            parent.setHideTimer();
        }
    };
    menu.setParent = function (p) {
        parent = p;
    }
    menu.setData = function (d) {
        data = d;
    }
    menu.preload = function () {
        if (!loaded)
            _load(false);
    };
    menu.destroy = function () {
        if (children.length > 0) {
            for (i = 0; i < children.length; i++) {
                children[i].destroy();
            }
        }
        menu.remove();
    }
    _initialize();
    return menu;
};

var MiniMenuItem = function (data, options, menu) {
    var conf = $.extend({}, $.fn.minimenu.defaults, options);
    var item = $("<li></li>");
    var status = false;
    var type = false;
    var child = false;

    var _initialize = function () {
        if (data.id)
            item.attr("rel", data.id);

        /** FOR OTHER TYPES THEN REGULAR **/
        if (data.type) {
            type = data.type;
            status = data.status;
            _initSpecialType();
        } else if (conf.showIcon) {
            if (data.icon)
                item.append("<img src='" + data.icon + "' class='mm-icon'/>");
            else
                item.append("<img src='" + conf.blankimg + "' class='mm-icon'/>");
        }

        if (data.label)
            item.append("<span>" + data.label + "</span><div class='mm-clear'></div>");

        if (data.children) {
            item.addClass("mm-container");
            var ob = new MiniMenu(conf);
            ob.setData(data.children);
            ob.setParent(menu);
            child = ob;
        } else {
            item.addClass("mm-item");
        }

        if (data.classname) {
            item.addClass(data.classname);
        }

        if (data.href) {
            item.click(function () {
                window.location.href = data.href;
            });
        }

        if (data.onclick) {
            if (!$.isFunction(data.onclick)) {
                try {
                    var customfunc = false;
                    eval("customfunc = " + data.onclick + ";");
                    if ($.isFunction(customfunc)) {
                        data.onclick = customfunc;
                    }
                } catch (e) {
                    //alert(e);
                }
            }
            if ($.isFunction(data.onclick)) {
                item.click(function () { data.onclick(item) });
            }
        }

        _createEvents();
    };

    _createEvents = function () {
        item.hover(function () {
            menu.hideChildren(false);
            $(this).addClass("mm-hover");
        }, function () {
            $(this).removeClass("mm-hover");
        });
        if (child) {
            item.mouseover(function () {
                var npos = {};
                menu.preload();
                var itemWidth = $(this).width();
                var itemTop = $(this).position().top;
                var itemHeight = $(this).height();
                var wwidth = $("body").width();
                var left = menu.getPosition().x + itemWidth;
                var top = menu.getPosition().y + itemTop /*- itemHeight*/;

                if (left + menu.width() > wwidth) {
                    left = menu.getPosition().x - (itemWidth / 2);
                }
                /*if(parent){
                npos.x = parent.getPosition().x + itemWidth;
                npos.y = parent.getPosition().y + itemTop;
                }else{*/
                npos.x = left;
                npos.y = top;
                //}
                child.setPosition(npos);
                child.addClass("mm-sub");
                child.show();
            });
        }
        item.mousedown(function () {
            $(this).addClass("mm-down");
        });
        item.mouseup(function () {
            $(this).removeClass("mm-down");
        });

        if (conf.onclick) {
            if (!$.isFunction(conf.onclick)) {
                try {
                    var customfunc = false;
                    eval("customfunc = " + conf.onclick + ";");
                    if ($.isFunction(customfunc)) {
                        conf.onclick = customfunc;
                    }
                } catch (e) {
                    //alert(e);
                }
            }
            if ($.isFunction(conf.onclick)) {
                item.click(function () { conf.onclick(item) });
            }
        }
        item.click(function () {
            $(this).removeClass("mm-down");
            if (!type) {
                menu.hide(true);
            }
        });
    };

    _initSpecialType = function () {
        if (type == "check") {
            var icon = "";
            if (status == "checked") {
                icon = conf.iconchecked;
            } else {
                icon = conf.iconunchecked;
                status = "unchecked";
            }
            item.append("<img src='" + icon + "' class='mm-icon'/>");

            item.click(function () {
                var icon = conf.iconchecked;
                if (status == "checked") {
                    icon = conf.iconunchecked;
                    status = "unchecked";
                } else {
                    status = "checked";
                }
                $("img", item).attr("src", icon);
            });
        }

    };

    item.setStatus = function (newStatus) {
        status = newStatus;
    };
    item.getStatus = function () {
        return status;
    };
    item.hideChild = function () {
        if (child) {
            child.hide(false);
        }
    };
    _initialize();
    return item;
};


/**
**	JQUERY EXTENSION
**/
(function ($) {
    $.fn.minimenu = function (options) {
        return this.each(function () {
            var element = $(this);
            if (element.data('minimenu')) return;
            var w = new MiniMenu(this, options);
            element.data('minimenu', w);
        });
    };

})(jQuery);


$.fn.minimenu.defaults = {
    source: "ajax",
    data: false, 	// FOR SUBITEMS
    method: "POST", 	// METHOD
    datatype: "json", 	// SOURCE DATATYPE - JSON / ELEMENT ($("ul")) - not yet implemented;
    url: '/', 		// AJAX URL
    params: {},  			// PARAMS TO POST
    preload: false, 	// PRELOAD DATA - AJAX
    showIcon: false, 	// SHOW ICON
    timeToHide: 500, 		// Time needed before the menu hides on mouseout	
    parent: false,
    evenclass: "",
    oddclass: "",
    classname: "",
    hasiconclass: "mm-hasicon",
    maxitems: false, 	//LIMIT NR OF VISIBLE MENU ITEMS
    scrollinterval: 150,
    blankimg: "/design/default/images/miniplugins/icons/blank.gif",
    iconchecked: "/design/default/images/miniplugins/icons/ui-check-box-mix.png",
    iconunchecked: "/design/default/images/miniplugins/icons/ui-check-box-uncheck.png",
    onshow: false, 	//FUNCTION TRIGGERED WHEN MENU IS SHOWN
    onhide: false, 	//FUNCTION TRIGGERED WHEN MENU IS HIDDEN
    width: 'auto'		//OR PX OR TRIGGER
};

/** DATA ELEMENT OPTIONS 
button {
id		:  "buttonid",
label	:  "the label",
onclick :  function(){ your action here },
href	:  "Path/To/Url",
icon	:  "Path/to/icon.gif",
classname: "extraclass",
type	:  "check",	  	   specialtypes not required
status	:  "unchecked",  - or checked when is a specialtype 
}***/

