/*
 * SmartTip
 *
 *
 */

initialise_smart_tip = true;

// Load CSS file specific to SmartTip
document.write('<link rel="stylesheet" href="/generic/js/SmartTip/SmartTip.css" type="text/css" />');

if(BrowserDetect.browser == "Explorer"  &&  BrowserDetect.version == 7) {
	document.write('<link rel="stylesheet" href="/generic/js/SmartTip/SmartTipIE7.css" type="text/css" />');
} else if(BrowserDetect.browser == "Explorer"  &&  BrowserDetect.version == 6) {
	document.write('<link rel="stylesheet" href="/generic/js/SmartTip/SmartTipIE6.css" type="text/css" />');
}

/*
 * 	SmartTip instantiation
 *
 *  option example: {type:'confirm', width:'small'}
 *  options.type can be 'standard', 'warning', 'yesno'
 *  options.width can be 'small', 'medium' or 'large'
 *
 */
function SmartTip(targetId, tipContent, options) {

	// set default options
	this.options = {
			type: 'standard',
			width: 'medium',
			responseHandler: null,
			horizontalDirection: 'right',
			anchorToTarget: false,
			xOffset: SmartTip.X_OFFSET,
			yOffset: SmartTip.Y_OFFSET,
			timeoutMs: SmartTip.TIMEOUT_MS,
			xPos: 200
			};

	if(SmartTip.ENABLED) {
		// override default options with any passed via constructor
		if (options) {
			if (options.type) this.options.type = options.type;
			if (options.width) this.options.width = options.width;
			if (options.responseHandler) this.options.responseHandler = options.responseHandler;
			if (options.horizontalDirection) this.options.horizontalDirection = options.horizontalDirection;
			if (options.anchorToTarget) this.options.anchorToTarget = options.anchorToTarget;
			if (options.xOffset != null) this.options.xOffset = options.xOffset;
			if (options.yOffset != null) this.options.yOffset = options.yOffset;
			if (options.timeoutMs > 100) this.options.timeoutMs = options.timeoutMs;
			if (options.xPos) this.options.xPos = options.xPos;
		}
		this.target = $(targetId);
		this.tipContent = tipContent;
		this.visible = false;

		if (this.options.type == 'standard') {
			Event.observe(this.target, 'mouseover', SmartTip.prototype.onMouseOver.bindAsEventListener(this));
			Event.observe(this.target, 'mouseout', SmartTip.prototype.onMouseOut.bindAsEventListener(this));
		}

		SmartTip.INSTANCES.push(this);
	}
}


//STATIC CLASS ATTRIBUTES
SmartTip.ZINDEX = 999;
SmartTip.MOUSE_X = 0;
SmartTip.MOUSE_Y = 0;
SmartTip.SCROLL_TOP = 0;
SmartTip.X_OFFSET = 5; /* IMPORTANT! Offset must ensure top doesn't overlap with mouse coordinates, for Firefox */
SmartTip.Y_OFFSET = -15; // px
SmartTip.FOOTER_HEIGHT = 0; // px  - leave as 0. This causes a break in the SmartTip if greater than 0, due to iFrame stretching
SmartTip.INSTANCES = Array();
SmartTip.TIP_FILE_DIRECTORY = '/Context';
SmartTip.TIMEOUT_MS = 180000;

SmartTip.RESPONSE_OBSERVERS = Array();
SmartTip.RESPONSE_OK = 1;
SmartTip.RESPONSE_CANCEL = 2;
SmartTip.ENABLED = true;

SmartTip.closeButton = '<div id="tipClose" onclick="SmartTip.hideTip();"></div>';

SmartTip.imageryPreloaded = Array();

//STATIC METHODS
SmartTip.initialise = function() {

	// Preload the imagery used, so it does not look dodgy when it first loads and the user does not have to wait for things
	SmartTip.imageryPreloaded[0] = new Image(); SmartTip.imageryPreloaded[0].src = '/generic/js/SmartTip/smarttip-background.gif';
	SmartTip.imageryPreloaded[1] = new Image(); SmartTip.imageryPreloaded[1].src = '/generic/js/SmartTip/smarttip-background-medium.gif';
	SmartTip.imageryPreloaded[2] = new Image(); SmartTip.imageryPreloaded[2].src = '/generic/js/SmartTip/smarttip-background-bottom-small.gif';
	SmartTip.imageryPreloaded[3] = new Image(); SmartTip.imageryPreloaded[3].src = '/generic/js/SmartTip/smarttip-background-bottom-medium.gif';
	SmartTip.imageryPreloaded[3] = new Image(); SmartTip.imageryPreloaded[3].src = '/generic/js/SmartTip/cross_grey.gif';

	// set up outer container
	var smartTipContainer = Builder.node('div', { id: 'smartTipContainer' });
	SmartTip.smartTipContainer = smartTipContainer; // maintain static reference to object

	// set up iframe backdrop (set width, and will resize later to match text container dynamically)
	var smartTipBackdrop = Builder.node('iframe', { id: 'smartTipBackdrop', frameborder: '0', scrolling: 'no', src:'/blank.htm' });
	smartTipBackdrop.style.zIndex = SmartTip.ZINDEX-1;
	smartTipContainer.appendChild(smartTipBackdrop);
	SmartTip.smartTipBackdrop = smartTipBackdrop; // maintain static reference to object

	// set up text container
	smartTipTextContainer = Builder.node('div', { id: 'smartTipTextContainer' });
	smartTipTextContainer.style.zIndex = SmartTip.ZINDEX;
	smartTipContainer.appendChild(smartTipTextContainer);
	SmartTip.smartTipTextContainer = smartTipTextContainer; // maintain static reference to object

	// set up footer
	smartTipFooter = Builder.node('div', {id: 'smartTipFooter'});
	smartTipFooter.style.zIndex = SmartTip.ZINDEX;
	smartTipContainer.appendChild(smartTipFooter);
	SmartTip.smartTipFooter = smartTipFooter; // maintain static reference to object

	document.body.appendChild(smartTipContainer);

	Event.observe(document, 'mousemove', SmartTip.updateMousePosition);
}

SmartTip.createSmartTipsByPhrase = function(phrases) {
	if(!SmartTip.ENABLED) {
		return;
	}
	var smartTipNo = 0;
	var smartTipPairs = Array();
	// get array of field labels
	var targetDivs = $$('label.rowLabel');
	// loop through each label, creating smartTips for each phrase
	for (var j=0; j<targetDivs.length; j++) {

		var labelText = targetDivs[j].innerHTML;

		for (var i=0; i<phrases.length; i++) {

			var regex = new RegExp('('+phrases[i]+')', "gi");
			labelText = labelText.replace(regex, '<span class="smartTipLink">$1</span>');

			if (targetDivs[j].innerHTML != labelText) {
				targetDivs[j].innerHTML = labelText;
				// go through and assign ids and observers to each SmartTip
				var children = targetDivs[j].descendants();
				for (var k=0; k<children.length; k++) {
					var child = children[k];
					if (child.hasClassName('smartTipLink') && !child.id) {
						var newId = "smartTip"+smartTipNo;
						child.id = newId;
						var tipFile = phrases[i].replace(/ /g,'_')+'.htm';
						smartTipPairs.push(Array(newId, tipFile));
						smartTipNo ++;
					}
				}
				labelText = targetDivs[j].innerHTML;   // label has been changed by adding ids
			}
		}
	}
	// create SmartTip objects
	for (var i=0; i<smartTipPairs.length; i++)
		new SmartTip(smartTipPairs[i][0], smartTipPairs[i][1]);
}

SmartTip.createSmartTipsByLabel = function(targetDivIds) {
	if(!SmartTip.ENABLED) {
		return;
	}
	var ele;
	var smartTipNo = 0;
	for (var i=0; i<targetDivIds.length; i++) {
		if (ele = $(targetDivIds[i])) {
			var children = ele.descendants();
			for (var k=0; k<children.length; k++) {
				if (children[k].hasClassName('rowLabel')) {
					var sTipId = 'smartTipLabel'+smartTipNo;
					children[k].innerHTML = '<span id="'+sTipId+'" class="smartTipLabel">' + children[k].innerHTML + '</span>';
					new SmartTip(sTipId, targetDivIds[i]+'.htm');
					smartTipNo ++;
				}
			}
		}
	}
}

SmartTip.createSmartTipsByID = function(targetIds) {
	if(!SmartTip.ENABLED) {
		return;
	}
	var ele;
	var smartTipNo = 0;
	for (var i=0; i<targetIds.length; i++) {
		var sTipId = 'smartTipID'+smartTipNo;
		if(!$(targetIds[i])) {
		  // Specified ID does not exist
			continue;
		}
		$(targetIds[i]).innerHTML = '<span id="'+sTipId+'" class="smartTipLabel">' + $(targetIds[i]).innerHTML + '</span>';
		new SmartTip(sTipId, targetIds[i]+'.htm');

		// Hide the title tag because the two conflict with each other
		$(targetIds[i]).title = '';

		smartTipNo ++;
	}
}

SmartTip.createSmartTipsByFile = function(file){
	if(!SmartTip.ENABLED) {
		return;
	}
	document.write('<label id="' + file + '" class="smartTipImage"><img src="/Graphics/script.gif" alt="Script"></label>');
	new SmartTip(file, file+'.htm', {width:'large'});
}
SmartTip.updateMousePosition = function(e) {
	if(!e) e=event;
	if (e.clientX) //if there is an x pos property
	{

		var scrollTop = 0;
		if (window.innerHeight) {
			scrollTop = window.pageYOffset;
		} else if (document.documentElement && document.documentElement.scrollTop) {
			scrollTop = document.documentElement.scrollTop;
		} else if (document.body) {
			scrollTop = document.body.scrollTop;
		}

	 	// Get mouse and vert scroll locations
		SmartTip.MOUSE_Y = e.clientY+scrollTop;
		SmartTip.SCROLL_TOP = scrollTop;

		// reposition an active SmartTip, if there is one
		/*for (var i=0; i<SmartTip.INSTANCES.length; i++) {
			if (SmartTip.INSTANCES[i].visible) {
				SmartTip.INSTANCES[i].setPosition();
			}
		}*/
	}
}

SmartTip.hideTip = function() {
	// hide tip
	SmartTip.smartTipContainer.style.visibility = 'hidden';

	// unload any response observers
	for (var i=0; i<SmartTip.RESPONSE_OBSERVERS.length; i++) {
		var obs = SmartTip.RESPONSE_OBSERVERS[i];
		if ($(obs.target))
			Event.stopObserving(obs.target, obs.event, obs.handler);
	}
}

//INSTANCE METHODS
SmartTip.prototype.setPosition = function(resizeBackdrop) {

	var newTop;
	if (this.options.anchorToTarget) {
		var targetPos = Position.cumulativeOffset(this.target);
		newTop = targetPos[1];
	} else {
		newTop = SmartTip.MOUSE_Y;
	}

	newTop = newTop - SmartTip.smartTipTextContainer.offsetHeight - SmartTip.FOOTER_HEIGHT + this.options.yOffset;

	if (newTop < SmartTip.SCROLL_TOP)
		SmartTip.smartTipContainer.style.top = SmartTip.SCROLL_TOP + "px";
	else
		SmartTip.smartTipContainer.style.top = newTop + "px";

  // This does not appear in IE, so lets fix the position (for all browsers) - it does not move horizontally!

	SmartTip.smartTipContainer.style.left = this.options.xPos + "px";

	if (resizeBackdrop) {
		SmartTip.smartTipBackdrop.style.height = (SmartTip.smartTipTextContainer.offsetHeight + SmartTip.FOOTER_HEIGHT)+'px';
		SmartTip.smartTipBackdrop.style.width = SmartTip.smartTipTextContainer.offsetWidth+'px';
	}
}

SmartTip.prototype.onMouseOver = function(event) {
	this.updateTipContent();
	return true;
}

SmartTip.smartTipFileCache = new Array();
SmartTip.prototype.updateTipContent = function() {

	if (this.tipContent.indexOf('.htm') > -1 && this.tipContent.indexOf('.htm') == this.tipContent.length - 4) {   // htm file specified in constructor
		var tipFile = this.tipContent;
		tipFile = SmartTip.TIP_FILE_DIRECTORY + '/' + tipFile;

	  // Do we have a cached version?
		if(SmartTip.smartTipFileCache[tipFile]) {
			this.showTip(SmartTip.smartTipFileCache[tipFile]);
			return;
		}

		// use ajax to update with the value of the text file
		SmartTip.smartTipTextContainer.innerHTML = "<p>loading tip...</p>";
		new Ajax.Request(tipFile, {
			method: 'get',
			onSuccess: function(resp) {
						 SmartTip.smartTipFileCache[tipFile] = resp.responseText;
						 this.showTip(resp.responseText);
						}.bind(this),
			onFailure: function() {
						 SmartTip.smartTipFileCache[tipFile] = '<p>tip missing ('+tipFile+')</p>';
						 this.showTip(SmartTip.smartTipFileCache[tipFile]);
						}.bind(this)
		});

	} else {  // Tip specified in constructor

		this.showTip(this.tipContent);

	}

}

SmartTip.prototype.showTip = function(tipText) {
	if(!SmartTip.ENABLED) {
		return;
	}

	SmartTip.smartTipTextContainer.innerHTML = SmartTip.closeButton + tipText;

	if (this.options.type == 'yesno') {
		SmartTip.smartTipTextContainer.appendChild(
				Builder.node('p', {className:'smart-tip-yesno-container'}, [
						Builder.node('a', {id:'smartTipResponse_Yes', href:'javascript://'}),
						Builder.node('a', {id:'smartTipResponse_No', href:'javascript://'}),
					])
			);
		$('smartTipResponse_Yes').innerHTML = '<img src="/Graphics/yes.gif" alt="Yes"/>';
		$('smartTipResponse_No').innerHTML = '<img src="/Graphics/no.gif" alt="No"/>';

		// obs.target, obs.event, obs.handler
		var obs = {target:'smartTipResponse_Yes', event:'click', handler: SmartTip.prototype.userResponse.bindAsEventListener(this,'yes')};
		SmartTip.RESPONSE_OBSERVERS.push(obs);
		Event.observe(obs.target, obs.event, obs.handler);

		obs = {target:'smartTipResponse_No', event:'click', handler: SmartTip.prototype.userResponse.bindAsEventListener(this,'no')};
		SmartTip.RESPONSE_OBSERVERS.push(obs);
		Event.observe(obs.target, obs.event, obs.handler);
	}

	SmartTip.smartTipContainer.className = this.options.type + ' ' + this.options.width
		+ '-'+this.options.horizontalDirection;
	SmartTip.smartTipContainer.style.visibility = 'visible';
	this.visible = true;
	if(SmartTip.smartTipTimer) clearTimeout(SmartTip.smartTipTimer); // clear any previous timeout
	SmartTip.smartTipTimer = setTimeout(SmartTip.prototype.onMouseOut, this.options.timeoutMs);
	this.setPosition(true);
}

SmartTip.prototype.userResponse = function(event, response) {

	// handle response using function reference passed via constructor
	this.options.responseHandler(response);

	// unload response observers?
	SmartTip.hideTip();
}

SmartTip.prototype.onMouseOut = function(event) {
	SmartTip.hideTip();
	this.visible = false;
	if(SmartTip.smartTipTimer) {
		clearTimeout(SmartTip.smartTipTimer);
	}
}
