/* This is a simple plugin to render action dropdown menus from html.
 * John Barlow - SugarCRM
 * add secondary popup implementation by Justin Park - SugarCRM
 *
 * The html structure it expects is as follows:
 *
 * <ul>                                     - Menu root
 *      <li>                                - First element in menu (visible)
 *      <ul class="subnav">		            - Popout menu (should start hidden)
 *          <li></li>                       - \
 *          ...                             -  Elements in popout menu
 *          <li></li>                       - /
 *          <li>
 *              <input></input>  - element contains submenu
 *              <ul class="subnav-sub">     - sub-popout menu (shown when mouseover on the above element)
 *                  <li></li>               - \
 *                  ...                     -  Elements in sub-popout menu
 *                  <li></li>               - /
 *              </ul>
 *          </li>
 *      </ul>
 *      </li>
 * </ul>
 *
 * By adding a class of "fancymenu" to the menu root, the plugin adds an additional "ab" class to the
 * dropdown handle, allowing you to make the menu "fancy" with additional css if you would like :)
 *
 * Functions:
 *
 * 		init: initializes things (called by default)... currently no options are passed
 *
 * 		Adds item to the menu at position index
 * 		addItem: (item, index)
 * 			item - created dom element or string that represents one
 * 			index(optional) - the position you want your new menuitem. If you leave this off,
 * 				the item is appended to the end of the list.
 *      	returns: nothing
 *
 *      Finds an item in the menu (including the root node "outside" the ul structure).
 * 		findItem: (item)
 * 			item - string of the menu item you are looking for.
 * 			returns: index of element, or -1 if not found.
 */
(function ($) {
  var methods = {
    init: function (options) {

      var menuNode = this;
      if (!this.hasClass("SugarActionMenu")) {
        //tag this element as a sugarmenu
        this.addClass("SugarActionMenu");

        //Fix custom code buttons programatically to prevent metadata edits
        this.find("input[type='submit'], input[type='button']").each(function (idx, node) {
          var jNode = $(node);
          var parent = jNode.parent();
          var _subnav = menuNode.find("ul.subnav");
          var _timer_for_subnav = null;
          var disabled = $(this).prop('disabled');
          var newItem = $(document.createElement("li"));
          var newItemA = $(document.createElement("a"));
          var accesskey = jNode.attr("accesskey");
          var accesskey_el = $("<a></a>");

          newItemA.html(jNode.val());
          if (!disabled) {
            newItemA.click(function (event) {
              if ($(this).hasClass("void") === false) {
                jNode.click();
              }
            });
          }
          else {
            newItemA.addClass("disabled");
          }
          newItemA.attr("id", jNode.attr("id"));
          accesskey_el.attr("id", jNode.attr("id") + "_accesskey");
          jNode.attr("id", jNode.attr("id") + "_old");


          if (accesskey !== undefined) {
            if ($('#' + accesskey_el.attr('id')).length === 0) {
              accesskey_el.attr("accesskey", accesskey).click(function () {
                jNode.click();
              }).appendTo("#content");
            }
            jNode.attr("accesskey", '');
          }

          //make sure the node we found isn't the main item of the list -- we don't want
          //to show it then.
          if (menuNode.sugarActionMenu("findItem", newItemA.html()) == -1) {
            parent.prepend(newItemA);
          }

          //make sub sliding menu
          jNode.siblings(".subnav-sub").each(function (idx, node) {
            var _menu = $(node);
            var _hide_menu = function () {
              if (_menu.hasClass("hover") === false)
                _menu.hide();
            };
            var _hide_timer = null;
            var _delay = 300;
            _menu.mouseover(function (evt) {
              if ($(this).hasClass("hover") === false)
                $(this).addClass("hover");
            }).mouseout(function (evt) {
              if ($(this).hasClass("hover"))
                $(this).removeClass("hover");
              if (_hide_timer)
                clearTimeout(_hide_timer);
              _hide_timer = setTimeout(_hide_menu, _delay);
            });

            newItemA.mouseover(function (evt) {
              $("ul.SugarActionMenu ul.subnav-sub").each(function (index, node) {
                $(node).removeClass("hover");
                $(node).hide();
              });
              var _left = parent.offset().left + parent.width() - newItemA.css("paddingRight").replace("px", "");
              var _top = parent.offset().top - _menu.css("paddingTop").replace("px", "");
              _menu.css({
                left: _left,
                top: _top
              });
              if (_menu.hasClass("hover") === false)
                _menu.addClass("hover");
              if (_subnav.hasClass("subnav-sub-handler") === false)
                _subnav.addClass("subnav-sub-handler");
              _menu.show();
            }).mouseout(function (evt) {
              _menu.removeClass("hover");
              _subnav.removeClass("subnav-sub-handler")
              if (_hide_timer)
                clearTimeout(_hide_timer);
              _hide_timer = setTimeout(_hide_menu, _delay);
            }).click(function (evt) {
              if (_timer_for_subnav)
                clearTimeout(_timer_for_subnav);
            }).addClass("void");
            menuNode.append(_menu);
          });
          jNode.css("display", "none");
        });

        //look for all subnavs and set them up
        this.find("ul.subnav").each(function (index, node) {
          var jNode = $(node);
          var parent = jNode.parent();
          var fancymenu = "";
          var slideUpSpeed = 1;
          var slideDownSpeed = 1;
          var dropDownHandle;

          //if the dropdown handle doesn't exist, lets create it and
          //add it to the dom
          if (parent.find("span").length == 0) {

            //create dropdown handle
            dropDownHandle = $(document.createElement("span"));
            parent.append(dropDownHandle);

          } else if (parent.find("span").length == 1) {
            dropDownHandle = $(parent.find("span"));
          } else {
            dropDownHandle = $(parent.find("span").first());
          }

          var toggleDropDown = function () {
            //close all other open menus
            //restore the dom elements back by handling iefix
            $("ul.SugarActionMenu > li").each(function () {
              $(this).sugarActionMenu('IEfix');
            });
            $("ul.SugarActionMenu ul.subnav").each(function (subIndex, node) {
              var subjNode = $(node);
              if (!(subjNode[0] === jNode[0])) {
                subjNode.slideUp(slideUpSpeed);
                subjNode.removeClass("ddopen");
              }
            });
            if (jNode.hasClass("ddopen")) {
              parent.sugarActionMenu('IEfix');
              //Bug#50983: Popup the dropdown list above the arrow if the bottom part is cut off .
              var _animation = {
                'height': 0
              };
              if (jNode.hasClass("upper")) {
                _animation['top'] = (dropDownHandle.height() * -1);
              }
              jNode.animate(_animation, slideUpSpeed, function () {
                $(this).css({
                  'height': '',
                  'top': ''
                }).hide().removeClass("upper ddopen");
              });
            }
            else {
              //To support IE fixed size rendering,
              //parse out dom elements out of the fixed element
              parent.sugarActionMenu('IEfix', jNode);
              var _dropdown_height = jNode.height(),
                _animation = {'height': _dropdown_height},
                _dropdown_bottom = dropDownHandle.offset().top + dropDownHandle.height() - $(document).scrollTop() + jNode.outerHeight(),
                _win_height = $(window).height();
              if (dropDownHandle.offset().top > jNode.height() && _dropdown_bottom > $(window).height()) {
                jNode.css('top', (dropDownHandle.height() * -1)).addClass("upper");
                _animation['top'] = (jNode.height() + dropDownHandle.height()) * -1;
              }

              jNode.height(0).show().animate(_animation, slideDownSpeed, function () {
                $(this).css('height', '');
                setTimeout(function () {
                  $('.subnav.ddopen').each(function (i, e) {
                    if (!$(e).hasClass('upper')) {
                      $(e).css('top', parseInt($(e).css('top')) + 10 + 'px');
                    }
                  })
                }, 2);
              });
              jNode.addClass("ddopen");
            }
          };

          //add click handler to handle
          dropDownHandle.click(function (event) {
            toggleDropDown();
            event.stopPropagation();
          });

          var parentDropDownHandler = parent.find('a').first().hasClass('parent-dropdown-handler');
          if (parentDropDownHandler) {
            parent.click(function (event) {
              dropDownHandle.click();
              event.stopPropagation();
            });
          }

          //add submenu click off to body
          var jBody = $("body");
          var _hide_subnav_delay = 30;
          var _hide_subnav = function (subnav) {
            if (subnav.hasClass("subnav-sub-handler") === false) {
              subnav.slideUp(slideUpSpeed);
              subnav.removeClass("ddopen");
            }
          }
          if (jBody.data("sugarActionMenu") != true) {
            jBody.data("sugarActionMenu", true);
            jBody.bind("click", function () {
              //retore the dom elements back by handling iefix
              $("ul.SugarActionMenu > li").each(function () {
                $(this).sugarActionMenu('IEfix');
              });

              $("ul.SugarActionMenu ul.subnav").each(function (subIndex, node) {
                //prevent hiding the submenu when user click the submenu which contains one more depth submenu
                var _hide = function () {
                  _hide_subnav($(node));
                }
                setTimeout(_hide, _hide_subnav_delay);
              });
              //Hide second depth submenu
              $("ul.SugarActionMenu ul.subnav-sub").each(function (subIndex, node) {
                var _hide = function () {
                  $(this).removeClass("hover");
                  $(this).hide();
                }
                _timer_for_subnav = setTimeout(_hide, _hide_subnav_delay);
              });

            });
          }

          //add hover handler to handle
          dropDownHandle.hover(function () {
            dropDownHandle.addClass("subhover");
          }, function () {
            dropDownHandle.removeClass("subhover");
          });


          //bind click event to submenu items to hide the menu on click
          jNode.find("li").each(function (index, subnode) {
            //prevent hiding the submenu when user click the submenu which contains one more depth submenu
            $(subnode).bind("click", function (evt) {
              var _hide = function () {
                _hide_subnav(jNode);
              }
              setTimeout(_hide, _hide_subnav_delay);
            });
          });

          //fix up text of <a> tags so they span correctly
          jNode.find("a").each(function (index, subnode) {
            $(subnode).html(function (index, oldhtml) {
              return oldhtml.replace(" ", "&nbsp;");
            });
          });
        });

        //Bug#51579: delete li tags which contains empty due to access role
        this.find(".subnav > li").each(function (index, subnode) {
          if ($(subnode).html().replace(/ /g, '') == '') {
            $(subnode).remove();
          }
        });
        //Bug#51579: If the first item is empty due to the access role,
        //           replace the first button from the first of the sub-list items.
        this.find("li.sugar_action_button:first").each(function (index, node) {
          var _this = $(node);
          var _first_item = $(node).find("a:first").not($(node).find(".subnav > li a"));
          if (_first_item.length == 0) {
            var sub_items = $(node).find(".subnav > li:first").children();
            if (sub_items.length == 0)
              menuNode.hide();
            else
              _this.prepend(sub_items);
          }
        });


      }
      return this;
    },
    addItem: function (args) {
      if (args.index == null) {
        this.find("ul.subnav").each(function (index, node) {
          $(node).append(args.item);
        })
      }
      else {
        this.find("ul.subnav").find("li").each(function (index, node) {
          if (args.index == index + 1) {
            $(node).before(args.item);
          }
        });
      }
      return this;
    },
    findItem: function (item) {
      var index = -1;
      this.find("a").each(function (idx, node) {
        var jNode = $(node);
        if ($.trim(jNode.html()) == $.trim(item)) {
          index = idx;
        }
      });
      return index;
    },
    /**
     * To support IE fixed size rendering,
     * parse out dom elements out of the fixed element
     *
     * Prepare ===
     * <div style=position:fixed>
     *     ...
     *     <li jquery-attached>
     *         <ul style=position:absoulte>
     *             ...
     *         </ul>
     *     </li>
     * </div>
     *
     * Application ===
     * <div style=position:fixed>
     *     <li ul-child-id='auto-evaluted-id'>
     *     ...
     *     </li>
     * </div>
     *
     * <ul id='auto-evaluted-id' style=position:fix;left/right/top-positioning:auto-calculated>
     *     ...
     * </ul>
     * @param this - element container which is inside the fixed box model
     * @param $ul - dropdown box model which needs to render out of the fixed box range
     *              if $ul is not given, it will restore back to the original structure
     */
    IEfix: function ($ul) {
      if ($ul) {
        if ($ul.hasClass('iefixed') === false)
          return;
        this.each(function () {
          SUGAR.themes.counter = SUGAR.themes.counter ? SUGAR.themes.counter++ : 1;
          var $$ = $(this),
            _id = $$.attr("ul-child-id") ? $$.attr("ul-child-id") : ($$.parent('.SugarActionMenu').attr("id")) ? $$.parent('.SugarActionMenu').attr("id") + 'Subnav' : 'sugaractionmenu' + SUGAR.themes.counter,
            _top = $$.position().top + $$.outerHeight(),
            _width = 'auto', //to obtain a certain size, apply min-width in css
            _css = {
              top: _top,
              width: _width,
              position: 'fixed'
            },
            _right = $('body').width() - $$.offset().left - $$.width(),
            _left = $$.offset().left;
          //fixed positioning depends on the css property
          if ($ul.css('right') != 'auto') {
            _css['right'] = _right;
          } else {
            _css['left'] = _left;
          }
          $('body').append($ul.attr("id", _id).addClass("SugarActionMenuIESub").css(_css));
          $$.attr("ul-child-id", _id);
        });

      } else {
        this.each(function () {
          var _id = $(this).attr("ul-child-id");
          $(this).append($("body>#" + _id).removeClass("SugarActionMenuIESub"));
        });
      }
    }
  }

  $.fn.sugarActionMenu = function (method) {

    if (methods[method]) {
      return methods[method].apply(this, Array.prototype.slice.call(
        arguments, 1));
    } else if (typeof method === 'object' || !method) {
      return methods.init.apply(this, arguments);
    } else {
      $.error('Method ' + method + ' does not exist on jQuery.tooltip');
    }
  }
})(jQuery);
