﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
// PopupMenu
// events published:
//		menuoptionselected
//
// menuItemCollection is an array of either strings and/or objects; if objects, the following properties are used: 
//		Text (a string - required), 
//		Enabled (a boolean - this is optional, defaults to 'true'), 
//		Value (an object, this is optional and will be passed back in the menuoptionselected event if present)
//		Checked (a boolean, if this property is present, a checkbox will be visible for each item that has this value, this is optional, returns menuItem object)
function PopupMenu(menuItemCollection, menuCssClass) {
	var that = this; // need this alias to get around closure scoping
	var thisPopupOverlayId = Guid.GetNew();
	var doc = getTopDocument();
	withDocument(doc, function() { // oh yeah, things get weird here...
	   var menuIsOpen = false;
	   var includeCheckBoxColumn = some(menuItemCollection, function(mi) { return (typeof (mi) != "string" && mi.hasOwnProperty("Checked")); });
	   var menuContainer = DIV({ "class": menuCssClass });
	   var selectHandler = function(mi, mc) {
	      if (mi.Enabled == true) {
	         if (mi.hasOwnProperty("Checked")) {
	            mi.Checked = !mi.Checked;
	         }
	         removeElement(mc);
	         withDocument(doc, function() {
	            if (getElement(thisPopupOverlayId)) {
	               removeElement(getElement(thisPopupOverlayId));
	            }
	         });
	         if (includeCheckBoxColumn) {
	            signal(that, "menuoptionselected", mi);
	         } else {
	            if (mi.Value) {
	               signal(that, "menuoptionselected", mi.Text, mi.Value);
	            } else {
	               signal(that, "menuoptionselected", mi.Text);
	            }
	         }
	      }
	   };
	   var menuDomItems = map(function(menuItem) {
	      if (menuItem == null) { return menuItem; }
	      if (typeof (menuItem) == "string") { menuItem = { Text: menuItem }; }
	      menuItem.Enabled = (menuItem.hasOwnProperty("Enabled")) ? menuItem.Enabled : true;
	      var checkBoxPlaceholder = null;
	      if (includeCheckBoxColumn && menuItem.hasOwnProperty("Checked")) {
	         var checkBox = INPUT({ type: "checkbox", checked: menuItem.Checked });
	         checkBoxPlaceholder = SPAN(null, checkBox);
	         connect(checkBoxPlaceholder, DomEvent.onclick, partial(selectHandler, menuItem, menuContainer));
	      } else if (includeCheckBoxColumn) {
	         var checkBox = INPUT({ type: "checkbox", style: StyleBuilder.visibilityHidden().end() });
	         checkBoxPlaceholder = SPAN(null, checkBox);
	      }
	      var text = SPAN(null, menuItem.Text);
	      var menuDomItem = A({ href: "javascript:void(0)", isEnabled: menuItem.Enabled, style: "display:block;" }, SPAN({ title: menuItem.Text }, checkBoxPlaceholder, text));
	      connect(menuDomItem, DomEvent.onclick, partial(selectHandler, menuItem, menuContainer));
	      return menuDomItem;
	   }, menuItemCollection);

	   appendChildNodes(menuContainer, menuDomItems);

	   that.Display = function(associatedElement) {
	      associatedElement = getElement(associatedElement); // allows client to pass element or id thereof
	      withDocument(getTopDocument(), function() {
	         appendChildNodes(getTopBody(), menuContainer);
	         var theStyle = StyleBuilder.positionAbsolute().zIndex(999).width("100%").height("100%").top(0).left(0).minHeight("100%").backgroundColor("#FFF").opacity(0).end();
	         var overlay = DIV({ id: thisPopupOverlayId, style: theStyle }); // for some reason, this only works *with* the opacity CSS stuff
	         appendChildNodes(getTopBody(), overlay); // this hidden div sits underneath the menu but on top of the page so that the user can click off of the menu to close it
	         connect(overlay, DomEvent.onclick, function() {
	            callAll(removeElement, overlay, menuContainer);
	         });
	         showElement(menuContainer);
	         LogObjectKeysAndValues(getElementPosition(menuContainer));
	         SetAssociatedElementDisplay(menuContainer, associatedElement, getElementDimensions(associatedElement).h);
	         LogObjectKeysAndValues(getElementPosition(menuContainer));
	         forEach(menuDomItems, function(menuDomItem) {
	            try {
	               if (menuDomItem && menuDomItem.isEnabled == false) {
	                  disableElement(menuDomItem);
	               }
	            } catch (e) { }
	         });
	      });
	   };
	   that.__dom__ = function() {
	      throw new Error("To display this menu, call the Display() method...");
	   };
	});
}
