/*
 * Constrains a variable between the 2 limits...
 *
 * i do belive that max/min combination should b a little more optimized than a if/else construction..
 * */
function constrain(n, lower, upper) {
	return Math.max(Math.min(upper,n),lower);
}

/*
 * notifies the current focused element, that a change had occured.
 *
 * Used by
 * 	- icon controls to notify the change of hidden elements.
 * 	- increment/decrement orderIndex to notify the change of the control
 * */
function notifyChangedElement(eventName,delay){
	if(Controls.getGlobal('focus')){
		delay=(delay?delay:'shortdelay');
		Controls.getGlobal('focus').onChange(null,eventName,delay);
	}
}

/*
 * prototype`s $F searches for an element by ID
 * $N will search for an element by i`ts name in #attributesContainer
 * */
function $N(elementName){
	var ret=$$('#attributesContainer input[name="'+elementName+'"]');
	return ret[0];
}

/* the main container(documentContainer) was clicked:) this should trigger a clearFocus() on the grid object
 * */
function containerClick(){
	var f=Controls.getGlobal('focus');
	if(f && !f.disableClickEvent){
		f.clearFocus();
	}
}

/*
 * functions for converting between units(mm,px,pt)
 * */

// aboveZero is unused here, only kept for compatibility with mm2px
function px2mm(px, aboveZero, rounding){
	if(!px) return 0;

	var gridCt=window.detectedSize;
	gridCt*=Controls.getGlobal('zoom');

	rounding=(rounding?rounding:0);

	var init=px/gridCt;
	var ret=Number(px/gridCt).toFixed(rounding);

	return ret;
}

function mm2px(mm, aboveZero, rounding){
	if(!mm) return 0;

	var gridCt=window.detectedSize;
	gridCt*=Controls.getGlobal('zoom');

	rounding=(rounding?rounding:0);

	var ret=Number(mm*gridCt).toFixed(rounding);
	if(aboveZero && ret<=0) ret=1;

	return ret;
}

function pt2px(pt){
	return Math.round(pt*Controls.getGlobal('zoom')/0.75);
}

/***********************************************************************/


/*
 * Detect the monitor DPI and write it to $(page_gridCt_).
 * Disabled for now... all tested monitors had the same constant value for this computation.
 * */
function detectMonitorSize(){
	/*var element=document.createElement('div');
	$(element).setStyle({width:'1000mm'});
	$('pageContent').appendChild(element);
	var dimensions=$(element).getDimensions();
	$(element).remove();

	window.detectedSize=(parseInt(dimensions.width)/1000);
	$('page_gridCt_').value=window.detectedSize;
	**/

	window.detectedSize=$F('page_gridCt_');

	return window.detectedSize;
}

/*
 * switch between 2 classes. usefull as a workaround for IE's incapability of adding :hover events to elements which are not href's
 * */
function switchClasses(element,class1,class2,element1,class11,class12){
	var visible=true;

	if(typeof(element1)=='boolean'){
		visible=element1;
		element1=null;
	}else
		visible=$(element).hasClassName(class1);

	if(visible){
		$(element).addClassName(class2);
		$(element).removeClassName(class1);
	}else{
		$(element).addClassName(class1);
		$(element).removeClassName(class2);
	}

	if(element1){
		if(visible){
			$(element1).addClassName(class12);
			$(element1).removeClassName(class11);
		}else{
			$(element1).addClassName(class11);
			$(element1).removeClassName(class12);
		}
	}
}


/*
 * called when expanding a variable.. browser workarounds
 * 	IE is buggy here too... it just won't recalculate the new dimension of the parent container. it really likes to show the scrollbars
 * */
function forceResizePanel(panel){
	switch(panel){
		case 'variables':
			// another IE bug. The scrollbar will not apper, and the container DIV will act like it has overflow:hidden if we do not force a resize of the container...
			$('tab_variables_container').setStyle({height:(Number(parseInt($('tab_variables_container').getStyle('height')))-1)+'px'});
			request_resizePanels('fast');
		break;
	}
}

/*
 * Used by variables, insert a text into destination
 *  crossbrowser
 * */
function insertText(sourceText,destination) {
	if(sourceText && $(destination)) {
		if (document.selection) {															//IE style
			$(destination).focus();
			sel = document.selection.createRange();
			sel.text = sourceText;
			$(destination).focus();
		}else if ($(destination).selectionStart || $(destination).selectionStart == "0") {	//MOZILLA/NETSCAPE style
			var scrollLeft=destination.scrollLeft;
			var scrollTop=destination.scrollTop;

			var startPos = $(destination).selectionStart;
			var endPos = $(destination).selectionEnd;
			var originalText = $(destination).value;
			$(destination).value = String(originalText).substring(0, startPos) + sourceText + String(originalText).substring(endPos, String(originalText).length);

			// move the cursor at the end of the inserted text
			$(destination).selectionStart=startPos+String(sourceText).length;
			$(destination).selectionEnd=startPos+String(sourceText).length;

			// keep the scollbars in place
			destination.scrollLeft=scrollLeft;
			destination.scrollRight=scrollTop;
		} else {
			$(destination).value += $(destination);
		}
		return true;
	}
	return false;
}

 /*
  * Used by variables, insert a text into destination
  *  crossbrowser
  * */
function insertTextAt(sourceText, destination) {
 	if(sourceText && $(destination)) {
 		if (document.selection) {															//IE style
 			$(destination).focus();
 			sel = document.selection.createRange();
 			sel.text = sourceText;
 			$(destination).focus();
 		}else if ($(destination).selectionStart || $(destination).selectionStart == "0") {	//MOZILLA/NETSCAPE style
 			var scrollLeft=destination.scrollLeft;
 			var scrollTop=destination.scrollTop;

 			var startPos = $(destination).selectionStart;
 			var endPos = $(destination).selectionEnd;
 			var originalText = $(destination).value;
 			$(destination).value = String(originalText).substring(0, startPos) + sourceText + String(originalText).substring(endPos, String(originalText).length);

 			// move the cursor at the end of the inserted text
 			$(destination).selectionStart=startPos;
 			$(destination).selectionEnd=startPos+String(sourceText).length;

 			// keep the scollbars in place
 			destination.scrollLeft=scrollLeft;
 			destination.scrollRight=scrollTop;
 		} else {
 			$(destination).value += $(destination);
 		}
 		return true;
 	}
 	return false;
 }

/*
 * Marks the page as busy, shows the overlayed throbber, etc
 * */
function markBusyPage(level,force){
	if(level==null)level=0;

	if(level!=0){ // mark the page as buzy
		$('pageLoadStatus').show();

		$('preDocumentContainer1').up().addClassName('throbberBig');

		if(level==1){
			$('preDocumentContainer1').hide();
		}else{
			$('preDocumentContainer1').setStyle({opacity:level});
		}

		Controls.globalCall('busy');
	}else{		// level=0, page is not busy anymore
		level=Controls.getGlobal('busyPage');
		var idle=Controls.isIdle();

		if(force)idle=true;

		if(idle==1){
			$('pageLoadStatus').hide();
			$('preDocumentContainer1').up().removeClassName('throbberBig');

			if(level==1){
				$('preDocumentContainer1').show();
			}else{
				$('preDocumentContainer1').setStyle({opacity:1.0});
			}

			Controls.dispatchEvent('onPageChanged');

			Controls.globalCall('idle');
		}else{
			$('pageLoadStatus').update(Math.round(Number(idle*100))+'%');
			eventScheduler.schedule('markBusyPage',markBusyPage.bind(0),0.5);
		}
	}

	Controls.setGlobal('busyPage',level);
}

/*****************************************************************************/

/*
 * visually "disables" an element.
 * 	in reality i add a "grayed" class, and set it as readonly, because disabled controls are not submitted by the browser.
 * */
function disableElement(element,disable){
	if(disable==null)disable=true;

	var type=$(element).type;
	if(type==null)type=$(element).nodeName;

	if(disable){
		$(element).addClassName('disabled');
		$(element).writeAttribute('readonly',true);

		// selectors do no have a "readonly" attribtue, so we must simulate it through JS
		// 		layer...? IE reports selectors as layers?
		if(type=='select-one' || type=='layer'){
			$(element).event_disableFocus=function(){this.blur();}.bind($(element));
			$(element).observe('focus',$(element).event_disableFocus);

			$(element).stored_selectedIndex=$(element).selectedIndex;
			$(element).event_disableChange=function(){this.selectedIndex=this.stored_selectedIndex;}.bind($(element));
			$(element).observe('change',$(element).event_disableChange);
		}
	}else{
		$(element).removeClassName('disabled');
		$(element).writeAttribute('readonly',false);

		// selectors do no have a "readonly" attribtue, so we must simulate it through JS
		// 		layer...? IE reports selectors as layers?
		if(type=='select-one' || type=='layer'){
			if($(element).event_disableFocus){
				$(element).stopObserving('focus',$(element).event_disableFocus);
				$(element).event_disableFocus=null;
			}

			if($(element).event_disableChange){
				$(element).stopObserving('change',$(element).event_disableChange);
				$(element).event_disableChange=null;
			}
		}
	}
}

/*
 * Used by containers, attach it to a <legend> tag, and it will toggle the content of the parent <fieldset>
 * */
function toggleContainer(container){
	$(container).next().toggle();

	// simulate a 'refresh click'
	if($(container).up('fieldset').select('a.reload').length==1) {
		updateAttribtuesVisibility($(container).up('fieldset').select('a.reload').first());
	}
}

/*
 * sets the preview's item background color. used by colorPickers
 * */
function setPreviewBackgroundColor(attributePanel,element,color){
	if(attributePanel){
		var preview=$$("#"+attributePanel.identify()+" div[id='"+element+"_preview']");
		var input=$$("#"+attributePanel.identify()+" input[id='"+element+"']");

		if(preview)preview=preview.first();
		if(input)input=input.first();

		if(preview){
			if(color!=''){
				preview.setStyle({backgroundColor:color,backgroundImage:'url()'});
			}
			else{
				preview.setStyle({backgroundColor:'transparent',backgroundImage:'url("_img/background/transparent.gif")'});
			}
		}
	}
}

/*
 * Emulates the <label>'s for='id_element' attribtue. because i have a lot of duplicate id's
 *
 * called on the onClick event
 * */
function emulateLabel_for(id,element,event){
	var checkbox=$(element).up().select('input[id="'+id+'"]').first();

	simulateEvent('click',checkbox);
}

 /*
 * Simulate an event on the specified object.
 * Should work cross-browser, but IE seems too subborn to work for all events...
 * */
function simulateEvent(eventStr,element){
	var element = $(element);
	var evt;

	if (document.createEvent){ // MOZ way
		switch(eventStr){
			case 'click':
				// see http://developer.mozilla.org/samples/domref/dispatchEvent.html for details
				evt = document.createEvent("MouseEvents");
				evt.initMouseEvent(eventStr, true, true, window,
    								0, 0, 0, 0, 0, false, false, false, false, 0, null);
			break;
			default:
				evt = document.createEvent("Event");
				evt.initEvent(eventStr, true, true);
		}

		return $(element).dispatchEvent(evt);
		//return document.getElementById($(element).identify()).dispatchEvent(evt);
	}

	if(element["on"+eventStr]){	// IE way (normally called, this methid uses the "onClick" way of naming the event handlers)
		return element["on"+eventStr]();
	}else if(element[eventStr]){	// IE way
		return element[eventStr]();
	}else{
		var newEventStr=String(eventStr).capitalize();

		if(element["on"+newEventStr]){
			return element["on"+newEventStr]();
		}
	}

	return false;
}

