var ContextMenu = Class.create();

ContextMenu.prototype = {

	items : [],

	target : null,

	status : 'hidden',

	initialized : false,

	options : {
				dropShadow: false,
				offX: 5,
				offY: 5,
				shadowOpacity: 1,
				showOnLeftClick: false
			  },

	initialize : function(target, items, options) {

							ContextMenu._currentInstance = this;

							target = target || Event.element();

							this.initialized = this.initialized || typeof target.__contextInitialised != 'undefined';

							if(!this.initialized) {

								this.options = Object.extend(this.options, options || {});

								if(Event.isLeftClick() && !this.options.showOnLeftClick) {

									return true;
								}

								if(!this.options.showOnLeftClick) {//looking for "oncontextmenu"

									while(!target.oncontextmenu) {

										if(!(target = target.parentNode) || (target.nodeType == 1 && target.tagName.toLowerCase() == 'body')) {

											alert('Could not fetch context menu\'s target element.');

											return true;

										} else {

											target.__contextInitialised = true;

										}

									}

								}

								this.initialized = target.__contextInitialised = true;

								this.target = target;

								Event.listen(document, 'mouseup', this.release.bind(this));

							}


							this.initX = Event.pointerX();
							this.initY = Event.pointerY();

							if(items) {
								this.build(items);
							}

							return false;

						},
	release : function(e) {

							//stop event propagandation
							//so that all ascendant nodes of target do not fire their oncontextmenu events
//							Event.stop(e);

							if(Event.isLeftClick()) {

								this.hide();

							}
							return;
//							Event.getEvent(e);
//
//							var trgt = Event.element();
//
//							var leftButton = Event.isLeftClick();
//
//							if(!leftButton && (this.target == trgt || (trgt.id && trgt.id.indexOf('cmi_') != -1))) {//left clicked on the same element
//
//								return;
//
//							}
//
//							if((this.target != trgt && (trgt.id && trgt.id.indexOf('cmi_') == -1))) {
//
//								document.oncontextmenu = function() {return true;};
//							}
//
//							this.status = 'hidden';
//
//							Element.hide('__contextDiv');
//
//							if(this.options.dropShadow) {
//								Element.hide('__contextDivShadow');
//							}

						},
	build : function(options) {

		//menu items have to have the following formats:
		//ARRAY - the menu items
		//ARRAY[i] - a menu item
		//ARRAY[i][0] - menu item's text
		//ARRAY[i][1] - menu item's onclick event
		//ARRAY[i][2] - whether the menu item is enabled

		this.items = options || this.items;

		if (!this.initialized ||
			!this.items.length ||
			(!this.options.showOnLeftClick && ['mouseup', 'mousedown', 'click'].indexOf(Event.type) != -1 && Event.isLeftClick())) {
			return true;
		}

		var ie5 = document.all&&document.getElementById
		var ns6 = document.getElementById&&!document.all

		var mouseX = this.initX;
		var mouseY = this.initY;

		//Find out how close the mouse is to the corner of the window
		var rightedge=ie5? document.body.clientWidth-Event.clientX : window.innerWidth-Event.clientX
		var bottomedge=ie5? document.body.clientHeight-Event.clientY : window.innerHeight-Event.clientY

		var menuobj = $('__contextDiv') || document.createElement('DIV');

		if(menuobj.id == '') {

			menuobj.id = '__contextDiv';
			menuobj.style.position = 'absolute';
			menuobj.style.zIndex = Element.getStyle(this.target, 'zIndex') + ((this.options.dropShadow)?2:1);
			menuobj.style.visibility = 'hidden';
			menuobj.className = 'ContextMenuHolder';

			var holder = document.getElementsByTagName('BODY')[0] || document.getElementsByTagName('HEAD')[0] || document;

			holder.appendChild(menuobj);
		}

		menuobj.innerHTML = '';

		var menu_width = Element.getStyle(menuobj, 'width');
		var auto_width = in_array(menu_width, ['auto','0px']);

		if(!auto_width) {//let the items define the menu width
			menuobj.style.width = 'auto';
		}

		var color = Element.getStyle(menuobj, 'backgoundColor');

		for(var i = 0; i < this.items.length; i++) {

			if(this.items[i].length == 0) {//a separator

				var item = document.getElementById('cmi_hr'+i) || document.createElement('HR');

				if(item.id == '') {

					item.id = 'cmi_hr'+i;

					item.className = 'ContextMenuSeparator';

					item.setAttribute('size', 1);

					Event.listen(item, 'mousedown', this.release)

					menuobj.appendChild(item);

				}

				continue;
			}

			var txt = this.items[i][1].replace(/\"/g, '\\"');

			var item = document.getElementById('cmi_'+i) || document.createElement('DIV');

			if(item.id == '') {

				item.id = 'cmi_'+i;

				item.className = 'ContextMenuItem';

				menuobj.appendChild(item);

			}

			Element.update(item, this.items[i][0]);

			if(typeof this.items[i][2] != 'undefined' && [false, 'false', 0, '0'].indexOf(this.items[i][2]) == -1) {//if not disabled

				if(txt != '') {

					try{
						eval('item.onclick = function(){try{'+txt+'}catch(e){if(DEBUG_MODE){alert("Context.failedonExecuting '+txt+': "+e.message)}}; Element.hide(this.parentNode)}');
					} catch (e) {

						if(DEBUG_MODE) {
							alert('Context.build.evalItemOnClick tried: ' + txt + '\n caught:' + e.message);
						}
					}
				}

				Event.listen(item, 'mouseover', (function() {this.className += ' cmihover'}).bind(item))
				Event.listen(item, 'mouseout', (function() {this.className = this.className.replace(/ cmihover/, '')}).bind(item))

			} else {

				Element.addClassName(item, 'dis');

				Element.setOpacity(item, .5);

			}

		}

		//if the horizontal distance isn't enough to accomodate the width of the context menu
		if (rightedge<menuobj.offsetWidth) {
			//move the horizontal position of the menu to the left by it's width
			menuobj.style.left = (ie5? mouseX-menuobj.offsetWidth : mouseX-menuobj.offsetWidth) + 'px'
		} else {
			//position the horizontal position of the menu where the mouse was clicked
			menuobj.style.left = (ie5? mouseX : mouseX) + 'px'
		}

		//same concept with the vertical position
		if (bottomedge<menuobj.offsetHeight) {
			menuobj.style.top = (ie5? mouseY-menuobj.offsetHeight : mouseY-menuobj.offsetHeight) + 'px'
		} else {
			menuobj.style.top = (ie5? mouseY : mouseY) + 'px'
		}

		this.status = "visible";

		if(menuobj.style.visibility == 'hidden') {

			menuobj.style.visibility = this.status;

		}

		Element.show(menuobj);

		if(this.options.dropShadow) {

			this.__dropShadow();

		}

		return false

	},

	__dropShadow: function() {

		var menuObj = $('__contextDiv');

		if(!menuObj) {

			return;

		}

		var shadow =  $('__contextDivShadow') || document.createElement('DIV');

		Element.hide(shadow);

		if(shadow.id == '') {

			shadow.id = '__contextDivShadow';

			menuObj.parentNode.insertBefore(shadow, menuObj);

			menuObj.parentNode.insertBefore(menuObj, shadow);

			Element.setStyle(shadow, {
										zIndex: Element.getStyle(menuObj, 'zIndex') - 1,
										position: 'absolute',
										visibility: 'visible',
										backgroundColor: 'black'
									 });

			Position.clone(menuObj, shadow, {offsetTop: this.options.offY, offsetLeft: this.options.offX});

		}

		if(parseInt(this.options.shadowOpacity) < 1) {
			Element.setOpacity(shadow, this.options.shadowOpacity);
		}

		Position.clone(menuObj, shadow, {offsetTop: this.options.offY, offsetLeft: this.options.offX});

		Element.show(shadow);

	},

	setCSS : function(css_file) {


		if(typeof ContextMenu.cssFile == 'undefined') {

			this.cssFile = document.createElement('LINK');

			ContextMenu.cssFile.id = 'ContextMenuCSS';

			ContextMenu.cssFile.setAttribute('rel', 'stylesheet');

			var holder = document.getElementsByTagName('BODY')[0] || document.getElementsByTagName('HEAD')[0] || document;

			holder.appendChild(ContextMenu.cssFile);
		}

		ContextMenu.cssFile.href = css_file;

	},

	hide: function() {

		Element.hide('__contextDiv');

		if(this.options.dropShadow) {
			Element.hide('__contextDivShadow');
		}

	}

}


//var ContextMenuOption = Class.create();
//
//ContextMenu.prototype = {
//
//	isParent: false, 		//shows whether there are sub menus for this option
//
//	type: 'option', 		//either 'option' OR 'separator'
//
//	text: null, 			//the text of the menu option (type has to be 'option', otherwise text is not used)
//
//	onClick: Prototype.emptyFunction, //what to do when the option is clicked
//
//	disabled: false, //what to do when the option is clicked
//
//	initialize: function (text, options) {
//
//		this.text = text || '';
//
//		this.__setOptions(options || {});
//
//	},
//
//	//private method
//	__setOptions: function (options) {
//
//		options = typeof options == 'object'?options:{};
//
//		for (var i in options) {
//
//			if(typeof this[i] != 'function') {
//
//				this[i] = options[i];
//
//			}
//
//		}
//
//	},
//
//	__build: function() {
//
//
//
//	}
//
//}
