/**
 * Universal JavaScript popup with multibrowser compatibility
 * 
 * @package		jsHint
 *
 * @author		ignat <iignatov@verasoft.com>
 * @version		1.0
 */


function jsHint(pId)
{
	this.id = pId;
	this.enabled = true;
	this.visible = false;
	this.container = jsHint_createContainer();
	this.ready = false;
	
	if (gBrowserInfo.supported && this.container)
	{
		this.Show = jsHint_show;
		this.Hide = jsHint_hide;
		this.Move = jsHint_move;
		this.setContent = jsHint_setContent;
		this.setStatus = jsHint_setStatus;
		this.LoadTemplate = jsHint_loadTemplate;
		this.LoadData = jsHint_loadData;
		this.Rebuild = jsHint_Rebuild;
		
		this.onMouseMove = jsHint_handleMouseMove;
		this.onLoadTemplate = jsHint_handleLoadTemplate;
		this.onLoadData = jsHint_handleLoadData;
		this.onRebuild = jsHint_handleRebuild;
		
		if (gBrowserInfo.type == gBrowserInfo.NS4)
		{
			document.captureEvents(Event.MOUSEMOVE);
		}
		appendEventHandlingCode('document', 'onmousemove', this.id+'.onMouseMove(e)');
	}
	else
	{
		this.show = jsHint_nop;
		this.hide = jsHint_nop;
		this.move = jsHint_nop;
		this.setContent = jsHint_nop;
	}
}


function jsHint_createContainer()
{
	// create hint container dynamically
	var container = document.createElement('div');
	// hide the hint container
	makeElementInvisible(container);
	// set hint container properties
	container.style.position = 'absolute';
	container.style.zIndex = 1000;
	// add hint to the document body
	document.getElementsByTagName("body").item(0).appendChild(container);
	
	return container;
}


function jsHint_loadTemplate(pTemplate)
{
	this.template = pTemplate;
	this.ready = false;
	
	this.onLoadTemplate();
}


function jsHint_loadData(pData)
{
	this.data = pData;
	this.ready = false;
	
	this.onLoadData();
}


function jsHint_setContent(txt)
{
	if ((gBrowserInfo.type == gBrowserInfo.IE4) || (gBrowserInfo.type == gBrowserInfo.IE5))
	{
		this.container.innerHTML = txt;
	}
	else if (gBrowserInfo.type == gBrowserInfo.NS4)
	{
		var lyr = this.container.document;
		lyr.write(txt);
		lyr.close();
	}
	else if (gBrowserInfo.type == gBrowserInfo.NS6)
	{
		var range = self.document.createRange();
		range.setStartBefore(this.container);
		var domfrag = range.createContextualFragment(txt);
		while (this.container.hasChildNodes())
		{
			this.container.removeChild(this.container.lastChild);
		}
		this.container.appendChild(domfrag);
	}
}

function jsHint_setStatus(enabled)
{
	this.enabled = (enabled && (enabled != "0"));
}


function jsHint_handleMouseMove(e)
{
	if (this.visible)
	{
		if (gBrowserInfo.type == gBrowserInfo.IE5)
		{
			var mouse_x = (event.x + self.document.body.scrollLeft);
			var mouse_y = (event.y + self.document.body.scrollTop);
		}
		else if (gBrowserInfo.type == gBrowserInfo.IE4)
		{
			var mouse_x = event.x;
			var mouse_y = event.y;
		}
		else if ((gBrowserInfo.type == gBrowserInfo.NS4) || (gBrowserInfo.type == gBrowserInfo.NS6))
		{
			var mouse_x = e.pageX;
			var mouse_y = e.pageY;
		}
		
		var offsetPoint = calculateOffsetPoint(this.container, mouse_x, mouse_y);
		moveElement(this.container, offsetPoint['x'], offsetPoint['y']);
	}
}


function jsHint_Rebuild()
{
	if (!this.ready && isSet(this.data) && isArray(this.data))
	{
		var lTemplate = this.template;
		
		var propRegex = new RegExp('([^a-z]?)this\\.([a-z][\\w\\.\\[\\]\\(\\)]+)', 'i');
		var matches;
		
		while (matches = lTemplate.match(propRegex))
		{
			eval("var lReplacement = this.data."+matches[2]+";");
			// this replacements are because of backrefences in regex replace patterns
			lTemplate = (lTemplate.replace(propRegex, matches[1]+lReplacement.replace(/\$/, '%dollar%'))).replace(/%dollar%/, '$');
		}
	
		this.setContent(lTemplate);
		this.ready = true;
		
		this.onRebuild();
	}
}


function checkCondition(pObject, pCondition)
{
	var result = false;
	var propRegex = /this\.(\w+)/;
	var matches;
	
	while (matches = pCondition.match(propRegex))
	{
		pCondition = pCondition.replace(propRegex, 'pObject["'+matches[1]+'"]');
		eval('var result = ' + pCondition + ';');
	}
	
	return result;
}


function jsHint_handleLoadTemplate()
{
	
}


function jsHint_handleLoadData()
{
	
}


function jsHint_handleRebuild()
{
	
}


function jsHint_show()
{
	if (!this.visible && (this.enabled))
	{
		if (!this.ready)
		{
			this.Rebuild();
		}
		makeElementVisible(this.container);
		this.visible = true;
	}
	return true;
}


function jsHint_hide()
{
	if (this.visible)
	{
		makeElementInvisible(this.container);
		this.visible = false;
	}
	return true;
}


function jsHint_move(x, y)
{
	if (this.visible && this.container)
	{
		moveElement(this.container, x, y);
	}
}


function jsHint_nop()
{
	return true;
}



// additional functions

function calculateOffsetPoint(pElement, mouse_x, mouse_y)
{
	var result = {"x":0, "y":0};
	
	if ((gBrowserInfo.type == gBrowserInfo.IE4) || (gBrowserInfo.type == gBrowserInfo.IE5))
	{
		var win_width = self.document.body.clientWidth;
		var win_height = self.document.body.clientHeight;
		var win_scroll_x = self.document.body.scrollLeft;
		var win_scroll_y = self.document.body.scrollTop;
		var pop_width_current = pElement.clientWidth;
		var pop_height_current = pElement.clientHeight;
		var scrollbar_size = 0;
	}
	else if (gBrowserInfo.type == gBrowserInfo.NS4)
	{
		var win_width = self.innerWidth;
		var win_height = self.innerHeight;
		var win_scroll_x = self.pageXOffset;
		var win_scroll_y = self.pageYOffset;
		var pop_width_current = pElement.offsetWidth;
		var pop_height_current = pElement.offsetHeight;
		var scrollbar_size = 16;
	}
	else if (gBrowserInfo.type == gBrowserInfo.NS6)
	{
		var win_width = self.outerWidth;
		var win_height = self.outerHeight;
		var win_scroll_x = self.pageXOffset;
		var win_scroll_y = self.pageYOffset;
		var pop_width_current = pElement.offsetWidth;
		var pop_height_current = pElement.offsetHeight;
		var scrollbar_size = 16;
	}
	
	// calculate horizontal position
	var pos_x = mouse_x + win_scroll_x + pop_offset_x;
	
	if ((pos_x + pop_width_current) > (win_width + win_scroll_x - scrollbar_size))
	{
		pos_x = win_width + win_scroll_x - pop_width_current - scrollbar_size;
	}
	if (pos_x < win_scroll_x)
	{
		pos_x = win_scroll_x;
	}
	
	// calculate vertical position
	var pos_y = mouse_y + pop_offset_y;

	if ((pos_y + pop_height_current) > (win_height + win_scroll_y - scrollbar_size))
	{
		pos_y = win_height + win_scroll_y - pop_height_current - scrollbar_size;
	}
	if (pos_y + pop_height_current > win_height + win_scroll_y - scrollbar_size)
	{
		pos_y = mouse_y - pop_height_current - pop_offset_y;
	}
	
	result = {"x":pos_x, "y":pos_y};
	
	return result;
}