/**
 * @description     prototype.js based context menu
 * @author          Juriy Zaytsev; kangax [at] gmail [dot] com; http://thinkweb2.com/projects/prototype/
 * @version         0.6
 * @date            12/03/07
 * @requires        prototype.js 1.6
 *
 * Modified by Danny Allen
*/

ContextMenu = Class.create({
	initialize: function() {
		var e = Prototype.emptyFunction;
		this.ie = Prototype.Browser.IE;
		this.bind = null;
		this.options = Object.extend({
			name: null,
			className: null,
			menuItems: null,
			title: null,
			pageOffset: 25,
			fade: false,
			zIndex: 1000,
			beforeShow: e,
			beforeHide: e,
			beforeSelect: e
		}, arguments[0] || { });

		this.shim = new Element('iframe', {
			style: 'position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);display:none',
			src: 'javascript:false;',
			frameborder: 0
		});

		this.options.fade = this.options.fade && !Object.isUndefined(Effect);


    if (!this.options.menuItems) {
			// don't show a menu
			this.container = new Element('div', {style: 'display:none;'});

		} else {
			// put items into menu
			this.container = new Element('div', {className: this.options.className, style: 'display:none;'});

			// add title header to menu?
      var headerStyle = "";
      if (!this.options.title) {
        headerStyle = " style=\"display:none;\"";
      }
			this.container.innerHTML = "<div id=\"menu_" + this.options.name + "_title\" class=\"menu_title\"" + headerStyle + ">" + this.options.title + "</div>";

			// insert items into menu
			var list = new Element('ul');


			// add placeholder for module-specified action
			tmpElement = new Element('li', {id: 'menu_' + this.options.name + '_extra_action', className: '', style: 'display:none'}).insert(
				Object.extend(new Element('a', {
					id: "menu_" + this.options.name + "_extra_action_item",
					href: '#',
					title: '',
					className: 'enabled'
				})
			));

			list.insert(tmpElement);


			// add standard actions
			var itemCounter = 0;
			this.options.menuItems.each(function(item) {
				// show shortcut in title tooltip?
				if (item.shortcut) {
					tmpTitle = item.name + ". " + item.shortcut;
				} else {
					tmpTitle = item.name;
				}

				// create menu entry
        tmpElement = new Element('li', {className: item.separator ? 'separator' : ''});

        if (item.separator) {
          itemContent = '';
          itemIcon = null;

        } else {
          if (item.className) {
            itemIcon = "<div class=" + item.className + "></div>";
          } else {
            itemIcon = null;
          }

          itemContent = Object.extend(new Element('a', {
                          id: "menu_" + this.options.name + "_item" + itemCounter,
                          href: '#',
                          title: tmpTitle,
                          className: item.disabled ? 'disabled' : 'enabled'
                        }), { _callback: item.callback })
                        .observe('click', this.onClick.bind(this))
                        .observe('contextmenu', Event.stop)
                        .update(item.name);
        }

        // insert menu entry into menu
        if (itemIcon) {
          tmpElement.insert(itemIcon);
        }
        tmpElement.insert(itemContent);

				// to allow separators to be individually manipulated, add id directly to them
				if (item.separator) {
					tmpElement.id = "menu_" + this.options.name + "_item" + itemCounter;
				}

				// insert entry into menu
				list.insert(tmpElement);

				++itemCounter;
			}.bind(this));
		}

		// insert menu into document
		$(document.body).insert(this.container.insert(list));
		if (this.ie) { $(document.body).insert(this.shim) }
	},
	clickHandler: function(e) {
    if ((!Prototype.Browser.Opera && e.ctrlKey) || (Prototype.Browser.Opera && !e.ctrlKey)) {
      return;
    }

    this.show(e);
	},
	show: function(e, div) {
    e.stop();

    // write context-based title into menu?
    var titleDiv = this.container.childElements()[0];

    if (typeof div == 'undefined') {
      div = e.element();
    }

    if (div) {
      tmpTitle = div.readAttribute('menutitle');

      if (titleDiv && tmpTitle) {
        titleDiv.innerHTML = tmpTitle.truncate(26);
        titleDiv.title = tmpTitle;
        titleDiv.show();
      }

    } else {
      if (titleDiv) {
        titleDiv.hide();
      }
    }


		this.options.beforeShow(e);
		var x = Event.pointer(e).x,
        y = Event.pointer(e).y,
        vpDim = document.viewport.getDimensions(),
        vpOff = document.viewport.getScrollOffsets(),
        elDim = this.container.getDimensions(),
        elOff = {
          left: ((x + elDim.width + this.options.pageOffset) > vpDim.width
            ? (vpDim.width - elDim.width - this.options.pageOffset) : x) + 'px',
          top: ((y - vpOff.top + elDim.height) > vpDim.height && (y - vpOff.top) > elDim.height
            ? (y - elDim.height) : y) + 'px'
        };

		this.container.setStyle(elOff).setStyle({zIndex: this.options.zIndex});

		if (this.ie) {
			this.shim.setStyle(Object.extend(Object.extend(elDim, elOff), {zIndex: this.options.zIndex - 1})).show();
		}

		this.options.fade ? Effect.Appear(this.container, {duration: 0.20}) : this.container.show();
		this.event = e;
	},
  hide: function() {
     this.container.hide();
  },
	onClick: function(e) {
		e.stop();
		if (e.target._callback && !e.target.hasClassName('disabled')) {
			this.options.beforeSelect(e);
			if (this.ie) {
        this.shim.hide();
      }

			this.container.hide();
			e.target._callback(this.event);
		}
	}
});
