/*
 * JQRDropMenu v 0.7
 * (c) 2009-2010 Radoslav Georgiev (valsodarg@gmail.com)
 *
 * Original Code/CSS Based On:
 * 	Droppy 0.1.2
 * 	(c) 2008 Jason Frame (jason@onehackoranother.com)
 *
 * Copyright (c) 2010, Radosalv Georgiev
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    This product includes software developed by the Radoslav Georgiev.
 * 4. Neither the name of the copyright holder nor the
 *    names of its contributors may be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL The COPYRIGHT HOLDER BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
    /*
 * TESTED ON:
 * Firefox 3.5.9
 * IE: 7/8/9
 * Safari: 4
 * Opera: 10.10
 */
    /**
 *TODO:
 *  Fix image max size/height (0.7.1)
 *  Fix the spacing/positioning for the child menus (0.7.3)
 *  Fix table defenition (cell) being too small) (0.7.5)
 *  Fix arrow sizing (0.7.7)
 *  Fix arrow icon to be always at the end (0.8)
 *  Compliance testing (fix bugs) (0.9.0)
 *	FF 3.6 (0.9.0)
 *	IE 7/8 (0.9.2)
 *	Safari 4 (0.9.4)
 *	Opera 10.50 (0.9.6)
 *	Konqueror (0.9.8)
 *	NonJS/Lynx (0.9.9)
 *
 *  Comment & compress (1.0.0)
 */
    $.fn.jqrdropmenu = function(options) {

        /********************* DEFAULT OPTIONS *********************/
        this.options = $.extend({
            fadeInTime: 500,
            fadeOutTime:300,
            arrowIconSize:"16px",
            imageMaxWidth : 30,
            imageMaxHeight: 30,
            imagePadding: 5,
            verticalIconClass:"ui-icon-triangle-1-s",
            horizontalIconClass:"ui-icon-triangle-1-e",
            delayInitialShow: 2000,
            rootVerticalOrientation: true,
            childVerticalOrientation: true,
            timeToWaitBeforeClose: 200,
            animateFirstTime : true,
            border: 0
        }, options || {}); // default options

        /********************* CLASS VARIABLES *********************/
        this.$jqItem = $(this);
        this.zIndex = 1000;
        this.makeMenuBarElement = function (rootItem, isRootBar)
        {
            var $menuItems = $(">li", rootItem);
            var $menuBar = $("<div class='jqrdropdownmenu_menu'><table cellspacing='0px' cellpadding='0px' width='100%' border='"+this.options.border+"' ></table></div>");
            var $table = $("table:first", $menuBar);
            var $tr;
            var i;

            if(isRootBar) $menuBar.addClass("jqrdropdownmenu_topmenu");
            if((isRootBar && !this.options.rootVerticalOrientation) || (!isRootBar && !this.options.childVerticalOrientation))
            {
                $table.append("<tr></tr>");
                $tr = $("tr:first", $table);
            }

            // max image size (calculate the span size)
            var maxImgW = 0;
            var maxImgH = 0;

            for(i = 0; i < $menuItems.size(); i++)
            {
                var $img = $(">img:first", $menuItems.get(i));
                var imgW = $img.width();
                var imgH = $img.height();
	    
                if(imgW > maxImgW) maxImgW = imgW;
                if(imgH > maxImgH) maxImgH = imgH;
            }

            if (maxImgW > this.options.imageMaxWidth) maxImgW = this.options.imageMaxWidth;
            if (maxImgH > this.options.imageMaxHeight) maxImgH = this.options.imageMaxHeight;

            for(i = 0; i < $menuItems.size(); i++)
            {
                if((isRootBar && !this.options.rootVerticalOrientation) || (!isRootBar && !this.options.childVerticalOrientation))
                    $tr.append($("<td class='jqrdropdownmenu_horizontal'></td>").append(this.makeMenuItemElement($menuItems.get(i), isRootBar, maxImgW, maxImgH)));
                else
                    $table.append($("<tr></tr>").append($("<td></td>").append(this.makeMenuItemElement($menuItems.get(i), isRootBar, maxImgW, maxImgH))));
            }

            $menuBar.hide();
            return $menuBar;
        }

        /**
         * Item structure
         * <span>
         *	<a>
         *	    <span>
         *		<span image />
         *		<span text />
         *		<span arrow />
         *	    </span>
         *	</a>
         *	<div submenu/>
         * </span>
         */
        this.makeMenuItemElement = function (item, isRootLevel, imageWidth, imageHeight)
        {
            var $item = $(item);
            var $img = $(">img:first", $item);
            var $subMenu = $(">ul:first", $item);
	
            var $text, $a;
            var iconStr;
            var $this;

            var $imgSpan = null;
            var $textSpan = null;
            var $arrowSpan = null;
            var $subMenuSpan = null;
            var $aInnerSpan = $("<span class='jqrdropdownmenu_item_innerSpan'></span>");
            var $menuItem = $("<span class='jqrdropdownmenu_item_rootSpan ui-state-default ui-widget jqrdropdownmenu'></span>");
	
            if(isRootLevel) $menuItem.addClass("jqrdropdownmenu_topitem");
            // add image
            if($img.size() > 0) {
                $imgSpan = $("<span class='jqrdropdownmenu_item_image' style='width: "+(imageWidth+this.options.imagePadding)+"px; height:"+imageHeight+"px;'></span>").append($img);
                $img.width(imageWidth);
                $img.height(imageHeight);
            }
            else
            {
                $imgSpan = $("<span class='jqrdropdownmenu_item_image' style='width: "+(imageWidth+this.options.imagePadding)+"px; height:"+imageHeight+"px;'>&nbsp;</span>")
            }

            // add link
            if($('>a', $item).size() != 0)
            {
                $a = $(">a:first", $item);
                $a.addClass("jqrdropdownmenu_a");
                $text = $a.html();
                $a.html("");
            }
            else {
                $a = $("<a class='jqrdropdownmenu_item_a'></a>");
                $text = $item.html();
            }
            $textSpan = $("<span class='jqrdropdownmenu_item_text'></span>").append($text);
	
            // add sub menu
            if($subMenu.size() > 0)
            {
                iconStr = "<span class='jqrdropdownmenu_item_arrow'><img style='width : "+this.options.arrowIconSize+"; height: "+this.options.arrowIconSize+";' src='style/images/blank.png' class='ui-icon ";
                if((isRootLevel && !this.options.rootVerticalOrientation) || (!isRootLevel && !this.options.childVerticalOrientation)) iconStr += this.options.verticalIconClass;
                else iconStr += this.options.horizontalIconClass;
                iconStr += "'></span>";
                $arrowSpan = $(iconStr);
                $subMenuSpan = this.makeMenuBarElement($subMenu, false);
            }

            // add show/hide thing
            $this = this;

            // add elements to each other
            $aInnerSpan.append($imgSpan);
            $aInnerSpan.append($textSpan);
            $aInnerSpan.append($arrowSpan);
            $a.append($aInnerSpan)
            $menuItem.append($a);
            $menuItem.append($subMenuSpan);

            // events
            $menuItem.hover(function () {
                $this.showItem(this);
            }, function() {
                $this.hideItem(this);
            } );
            $menuItem.click(function() {
                $this.hideItem(this);
            });
            return $menuItem;
        }

        this.hideItem = function(menuElement) {
            var $subMenu = $(">div:first", menuElement);
            $(menuElement).removeClass("ui-state-hover");

            if ($subMenu.size() == 0) return;
	
            $subMenu.data('cancelHide', false);
            var $this = this;
            setTimeout(function() {
                if (! $subMenu.data('cancelHide')) {
                    $this.zIndex --;
                    $subMenu.stop().fadeOut($this.options.fadeOutTime);
                }
            }, this.options.timeToWaitBeforeClose);
        }

        function parseCSSValue(t)
        {
            if(t == "") t = 0;
            else if(t == undefined) t = 0;
            else if (t == NaN) t = 0;
            else t = this.parseInt(t);
            return t;
        }

        this.showItem = function(menuElement) {
            var $menuItem = $(menuElement);
            $menuItem.addClass("ui-state-hover");
            var $subMenu = $(">div:first", $menuItem);

            var l = parseCSSValue($menuItem.width())+parseCSSValue($menuItem.css("padding-left"))+parseCSSValue($menuItem.css("padding-right"))+2*parseCSSValue($menuItem.css("padding")); // + par.offset().left;
            var t = parseCSSValue($menuItem.height())+parseCSSValue($menuItem.css("padding-top"))+parseCSSValue($menuItem.css("padding-bottom"))+2*parseCSSValue($menuItem.css("padding")); // + par.offset().left;
	
	
            if($menuItem.hasClass("jqrdropdownmenu_topitem"))
            {
                if(this.options.rootVerticalOrientation) t = 0;
                else l = 0;
            }
            else
            {
                if(this.options.childVerticalOrientation) t = 0;
                else l = 0;
            }
            $menuItem.children("div").css("left",l);
            $menuItem.children("div").css("top",t);

            if ($subMenu.size() == 0) return;
            $subMenu.data('cancelHide', true);

            $subMenu.css({
                zIndex: this.zIndex ++
            }).stop().fadeTo( this.options.fadeInTime, 1.0);
        }
    
        /********************* INITIALIZATION *********************/
        this.$rootBar = this.makeMenuBarElement($(">ul", this.$jqItem), true);
        this.$rootBar.css({ zIndex: this.zIndex })
        this.$jqItem.empty();
        this.$jqItem.append(this.$rootBar);
        this.$jqItem.hide();
        this.$jqItem.css("overflow", "visible");
        this.$jqItem.css("height", "auto");

        if(this.options.animateFirstTime)
        {
            this.$jqItem.fadeIn(this.options.delayInitialShow);
            this.$rootBar.fadeIn(this.options.delayInitialShow);
        }else
        {
            this.$jqItem.show();
            this.$rootBar.show();
        }

    };
