dojo.require("dijit._base.place");
dojo.require("dojo.string");

if (!Array.prototype.indexOf)
{
	Array.prototype.indexOf = function(elt /*, from*/)
	{
		var len = this.length;

		var from = Number(arguments[1]) || 0;
		from = (from < 0)
			? Math.ceil(from)
			: Math.floor(from);

		if (from < 0)
			from += len;

		for (; from < len; from++)
		{
			if (from in this && this[from] === elt)
				return from;
		}
		return -1;
	};
}

String.prototype.replaceAll = function(str_to_replace, replacement_str)
{
	var last_replacement_index = 0;
	var subject = this;

	if(subject.indexOf(str_to_replace) == -1)
		return subject;



	while(subject.indexOf(str_to_replace, last_replacement_index)>=0)
	{
		last_replacement_index = subject.indexOf(str_to_replace, last_replacement_index) + replacement_str.length;
		subject = subject.replace(str_to_replace, replacement_str);
	}

	return subject;
}

String.prototype.trim = function()
{
	var subject = this;
	return subject.replace(/^\s+|\s+$/g, '');
}

/* This utility function resolves the string movieName to a Flash object reference based on browser type. */
function GetMovieObj(movieName)
{
	if (navigator.appName.indexOf("Microsoft") != -1)
	{
		return window[movieName];
	}
	else
	{
		return document[movieName];
	}
}


// ========================================================
// declare the JSFeature namespace
var JSFeature = {};
JSFeature.white_out_box_connect_handle_onscroll = null;
JSFeature.white_out_box_connect_handle_onresize = null;
JSFeature.center_on_screen_connect_handle_onscroll = null;
JSFeature.center_on_screen_connect_handle_onresize = null;
JSFeature.center_on_screen_node_array = new Array();

JSFeature.Round = function(num, precision)
{
	var result;

	if(precision < 1)
	{
		result = Math.round(num);
	}
	else
	{
		result = Math.round(num*100000)/(100000);
		result = Math.round(num*10*precision)/(10*precision);
	}

	return result;
}

/**
*
*  Base64 encode / decode
*  http://www.webtoolkit.info/
*
**/

JSFeature.Base64 = {

	// private property
	_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

	// public method for encoding
	encode : function (input) {
		var output = "";
		var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
		var i = 0;

		input = JSFeature.Base64._utf8_encode(input);

		while (i < input.length) {

			chr1 = input.charCodeAt(i++);
			chr2 = input.charCodeAt(i++);
			chr3 = input.charCodeAt(i++);

			enc1 = chr1 >> 2;
			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
			enc4 = chr3 & 63;

			if (isNaN(chr2)) {
				enc3 = enc4 = 64;
			} else if (isNaN(chr3)) {
				enc4 = 64;
			}

			output = output +
			this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
			this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);

		}

		return output;
	},

	// public method for decoding
	decode : function (input) {
		var output = "";
		var chr1, chr2, chr3;
		var enc1, enc2, enc3, enc4;
		var i = 0;

		input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

		while (i < input.length) {

			enc1 = this._keyStr.indexOf(input.charAt(i++));
			enc2 = this._keyStr.indexOf(input.charAt(i++));
			enc3 = this._keyStr.indexOf(input.charAt(i++));
			enc4 = this._keyStr.indexOf(input.charAt(i++));

			chr1 = (enc1 << 2) | (enc2 >> 4);
			chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
			chr3 = ((enc3 & 3) << 6) | enc4;

			output = output + String.fromCharCode(chr1);

			if (enc3 != 64) {
				output = output + String.fromCharCode(chr2);
			}
			if (enc4 != 64) {
				output = output + String.fromCharCode(chr3);
			}

		}

		output = JSFeature.Base64._utf8_decode(output);

		return output;

	},

	// private method for UTF-8 encoding
	_utf8_encode : function (string) {
		string = string.replace(/\r\n/g,"\n");
		var utftext = "";

		for (var n = 0; n < string.length; n++) {

			var c = string.charCodeAt(n);

			if (c < 128) {
				utftext += String.fromCharCode(c);
			}
			else if((c > 127) && (c < 2048)) {
				utftext += String.fromCharCode((c >> 6) | 192);
				utftext += String.fromCharCode((c & 63) | 128);
			}
			else {
				utftext += String.fromCharCode((c >> 12) | 224);
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}

		}

		return utftext;
	},

	// private method for UTF-8 decoding
	_utf8_decode : function (utftext) {
		var string = "";
		var i = 0;
		var c = c1 = c2 = 0;

		while ( i < utftext.length ) {

			c = utftext.charCodeAt(i);

			if (c < 128) {
				string += String.fromCharCode(c);
				i++;
			}
			else if((c > 191) && (c < 224)) {
				c2 = utftext.charCodeAt(i+1);
				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
				i += 2;
			}
			else {
				c2 = utftext.charCodeAt(i+1);
				c3 = utftext.charCodeAt(i+2);
				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}

		}

		return string;
	}

}

JSFeature.CreateCookie = function(name,value,days)
{
	if(days)
	{
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else
		var expires = "";

	document.cookie = name+"="+value+expires+"; path=/";
}

JSFeature.ReadCookie = function(name)
{
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++)
	{
		var c = ca[i];
		while (c.charAt(0)==' ')
			c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0)
			return c.substring(nameEQ.length,c.length);
	}
	return null;
}

JSFeature.EraseCookie = function(name)
{
	JSFeature.CreateCookie(name,"",-1);
}


JSFeature.HtmlEntities = function(text)
{
	text = text.replaceAll('"', '&quot;');
	text = text.replaceAll('<', '&lt;');

	return text;
}
JSFeature.IsValidEmailAddress = function(address)
{
	var reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
	if(reg.test(address) == false)
	{
		return false;
	}
	return true;
}
JSFeature.AppendNodeToBody = function(node)
{
	var body_tag = dojo.query('body')[0];
	body_tag.appendChild(node);
}
JSFeature.RemoveNode = function(node)
{
	//var body_tag = dojo.query('body')[0];
	node.parentNode.removeChild(node);
}

JSFeature.WhiteOutNode = function(id, opacity, color, z_index)
{
	var node = document.getElementById(id);
	var bounding_box_obj = JSFeature.GetNodeBoundingBox(node);

	var new_div = document.createElement('div');

	// Append to the body
	JSFeature.AppendNodeToBody(new_div);// NOTE: appending to "new_div" throws off the positioning because the position of new_div may end up being relative to one of it's parents

	new_div.id 			= 'local_node_white_out_'+node.id;

	new_div.style.position 	= 'absolute';
	new_div.style.display 	= 'block';
	new_div.style.zIndex 	= node.style.zIndex + 1;
	new_div.style.left 		= bounding_box_obj.left + 'px';
	new_div.style.top 		= bounding_box_obj.top + 'px';
	new_div.style.width 	= bounding_box_obj.width + 'px';
	new_div.style.height 	= bounding_box_obj.height + 'px';

	dojo.style(new_div, "opacity", opacity ? opacity : .5);
	dojo.style(new_div, "backgroundColor", color ? color : "black");

	new_div.innerHTML = '';
}

JSFeature.UnWhiteOutNode = function(id)
{
	//var wo_obj = document.getElementById('local_node_white_out_'+id);
	//wo_obj.parentNode.removeChild(wo_obj);

	JSFeature.RemoveNode(document.getElementById('local_node_white_out_'+id));
}

JSFeature.CenterNodeOnNode = function(src_node, target_node)
{
	var bounding_box_obj = JSFeature.GetNodeBoundingBox(target_node);

	//target_node.appendChild(src_node);
	JSFeature.AppendNodeToBody(src_node);

	src_node.style.position = 'absolute';
	src_node.style.zIndex = target_node.style.zIndex + 2;

	src_node.style.left = (bounding_box_obj.left + bounding_box_obj.width / 2 - src_node.offsetWidth / 2) + 'px';
	src_node.style.top = (bounding_box_obj.top + bounding_box_obj.height / 2 - src_node.offsetHeight / 2) + 'px';
}

JSFeature.RemoveCenterNodeOnNode = function(target_node)
{
	JSFeature.RemoveNode(target_node);
}

JSFeature.ShowWhiteOut = function(opacity, color, z_index)
{
	JSFeature.HideWhiteOut();
	if(!JSFeature.white_out_box_connect_handle_onscroll)
	{
		JSFeature.white_out_box_connect_handle_onscroll = dojo.connect(window, "onscroll", JSFeature._AdjustWhiteOut);
	}
	if(!JSFeature.white_out_box_connect_handle_onresize)
	{
		JSFeature.white_out_box_connect_handle_onresize = dojo.connect(window, "onresize", JSFeature._AdjustWhiteOut);
	}
	var wo_obj = dojo.byId('feature_white_out');
	if(!wo_obj)
	{
		var wo_obj = document.createElement('div');
		wo_obj.id = 'feature_white_out';
		dojo.style(wo_obj, "opacity", opacity ? opacity : .5);
		dojo.style(wo_obj, "backgroundColor", color ? color : "black");
		wo_obj.style.display = 'block';
		wo_obj.style.position = 'absolute';
		wo_obj.style.zIndex = (z_index ? z_index : "1000");
		wo_obj.innerHTML = '';
		JSFeature.AppendNodeToBody(wo_obj);
	}

	JSFeature._AdjustWhiteOut();
}

JSFeature._AdjustWhiteOut = function(css_class_name)
{
	var wo_obj = dojo.byId('feature_white_out');
	if(wo_obj)
	{
		var vp_obj = dijit.getViewport();
		wo_obj.style.width = vp_obj.w + 'px';
		wo_obj.style.height = vp_obj.h + 'px';
		wo_obj.style.left = vp_obj.l + 'px';
		wo_obj.style.top = vp_obj.t + 'px';
	}
}
JSFeature.HideWhiteOut = function(css_class_name)
{
	var wo_obj = dojo.byId('feature_white_out');

	if(wo_obj)
	{
		if(JSFeature.white_out_box_connect_handle_onscroll)
		{
			dojo.disconnect(JSFeature.white_out_box_connect_handle_onscroll);
			JSFeature.white_out_box_connect_handle_onscroll = null;
		}

		if(JSFeature.white_out_box_connect_handle_onresize)
		{
			dojo.disconnect(JSFeature.white_out_box_connect_handle_onresize);
			JSFeature.white_out_box_connect_handle_onresize = null;
		}

		JSFeature.RemoveNode(wo_obj);
	}
}

JSFeature.CenterOnScreen = function(node)
{
	JSFeature.center_on_screen_node_array.push(node);

	if(!JSFeature.center_on_screen_connect_handle_onscroll)
	{
		JSFeature.center_on_screen_connect_handle_onscroll = dojo.connect(window, "onscroll", JSFeature._UpdateCenterOnScreen);
	}
	if(!JSFeature.center_on_screen_connect_handle_onresize)
	{
		JSFeature.center_on_screen_connect_handle_onresize = dojo.connect(window, "onresize", JSFeature._UpdateCenterOnScreen);
	}

	JSFeature._UpdateCenterOnScreen();
}

JSFeature.StopCenterOnScreen = function(node)
{
	try
	{
		var tmp_array = JSFeature.center_on_screen_node_array;
		JSFeature.center_on_screen_node_array = new Array();
		var i;
		var cur_node;
		for(i=0; i<tmp_array.length; i++)
		{
			cur_node = tmp_array[i];
			if(cur_node != node)
			{
				JSFeature.center_on_screen_node_array.push(cur_node);
			}
		}
	}
	catch(e)
	{
	}
}

JSFeature._UpdateCenterOnScreen = function()
{
	try
	{
		var i;
		var node, vp_obj, nw, nh, new_w, new_h;
		for(i=0; i<JSFeature.center_on_screen_node_array.length; i++)
		{
			node = JSFeature.center_on_screen_node_array[i];
			vp_obj = dijit.getViewport();
			nw = node.offsetWidth;
			nh = node.offsetHeight;

			new_w = (vp_obj.w/2 - nw/2) + vp_obj.l;
			new_h = (vp_obj.h/2 - nh/2) + vp_obj.t;

			node.style.left = new_w > 0?new_w + 'px':'0px';
			node.style.top = new_h > 0?new_h + 'px':'0px';
		}
	}
	catch(e)
	{
	}
}

JSFeature.GetNodePosArray = function(obj)
{
	var from_parent_only = false;//todo: Send this in as a param?

	var curleft = curtop = 0;
	if (obj.offsetParent)
	{
		if(from_parent_only)
		{
			return [obj.offsetLeft, obj.offsetTop];
		}
		else
		{
			do
			{
				curleft += obj.offsetLeft;
				curtop += obj.offsetTop;
			} while (obj = obj.offsetParent);
		}

	}

	return [curleft,curtop];
}

// left, top, width, height
JSFeature.GetNodeBoundingBox = function(obj)
{
	var left = 0;
	var top = 0;
	var width = 0;
	var height = 0;
	var right = 0;
	var bottom = 0;

	var tmp_pos_array = JSFeature.GetNodePosArray(obj);

	left = tmp_pos_array[0];
	top = tmp_pos_array[1];
	width = obj.offsetWidth;
	height = obj.offsetHeight;
	right = left + width;
	bottom = top + height;

	return {'left':left,'top':top,'width':width,'height':height,'right':right,'bottom':bottom};
}

// ========================================================
// declare error box registry namespace
var TWErrorRegistry = {obj_reg:[]};
TWErrorRegistry.AddObj = function(obj)
{
	var i;
	for(i=0; i<this.obj_reg.length; i++)
	{
		if(this.obj_reg[i].id == obj.id)
		{
			this.obj_reg[i] = obj;
			return;
		}
	}

	this.obj_reg.push(obj);
}
TWErrorRegistry.GetObj = function(id)
{
	var i;
	for(i=0; i<this.obj_reg.length; i++)
	{
		if(this.obj_reg[i].id == id)
			return this.obj_reg[i];
	}
}
// declare the TWError class
function TWError(parent_node, id, css_id)
{
	this.id = id;
	this.css_id = css_id;
	this.title;
	this.message_array = new Array();
	this.custom_create_callback = null;
	this.parent_node = null;

	this.SetTitle('The following errors have occured:');
	this.SetParentNode(parent_node);
	this.Hide();
	TWErrorRegistry.AddObj(this);

}

TWError.prototype.SetParentNode = function(parent_node)
{
	this.parent_node = parent_node;
}

TWError.prototype._pri_DefaultHTML = function()
{
	var i;
	var output = '';
	output += 	'<div id="'+this.id+'_error_box" class="'+(this.css_id?this.css_id+'_':'')+'error_box" style="display:none;">';
	output += 		'<div id="'+this.id+'_error_box_hide_link_wrapper" class="'+(this.css_id?this.css_id+'_':'')+'error_box_hide_wrapper">';
	output += 			'<div id="'+this.id+'_error_box_hide_link" class="'+(this.css_id?this.css_id+'_':'')+'error_box_hide_link" onclick="TWErrorRegistry.GetObj(\''+this.id+'\').Hide();">';
	output += 				'[close]';
	output += 			'</div>';
	output += 		'</div>';
	output += 		'<div id="'+this.id+'_error_box_title_wrapper" class="'+(this.css_id?this.css_id+'_':'')+'error_title_wrapper">'
	output += 			'<div id="'+this.id+'_error_box_title" class="'+(this.css_id?this.css_id+'_':'')+'error_title">'+this.title+'</div>';
	output += 		'</div>'
	output += 		'<div id="'+this.id+'_error_box_message_wrapper" class="'+(this.css_id?this.css_id+'_':'')+'error_box_message_wrapper">'
	output += 			'<ul>';
	for(i=0; i<this.GetErrorMessageCount(); i++)
	{
		output += 			'<li id="'+this.id+'_error_box_message_'+(i+1)+'" class="'+(this.css_id?this.css_id+'_':'')+'error_box_message">'+this.message_array[i]+'</li>';
	}
	output += 			'</ul>';
	output += 		'</div>';
	output += 	'</div>';

	return output;
}

TWError.prototype.SetCustomCreateCallback = function(callback)
{
	this.custom_create_callback = callback;
}


TWError.prototype._pri_CreateHTML = function()
{
	if(this.custom_create_callback)
		return this.custom_create_callback(this);
	else
		return this._pri_DefaultHTML();
}

TWError.prototype.Create = function()
{
	if(this.parent_node)
	{
		this.parent_node.innerHTML = this._pri_CreateHTML();
	}
}
TWError.prototype.Delete = function()
{
	if(this.parent_node)
	{
		this.parent_node.innerHTML = '';
	}
}
TWError.prototype.Show = function()
{
	this.Create();

	if(this.parent_node)
		this.parent_node.style.display = '';

	if(document.getElementById(''+this.id+'_error_box'))
	{
		document.getElementById(''+this.id+'_error_box').style.display = '';
	}
}

TWError.prototype.Hide = function()
{
	this.Create();

	if(this.parent_node)
		this.parent_node.style.display = 'none';

	if(document.getElementById(''+this.id+'_error_box'))
	{
		document.getElementById(''+this.id+'_error_box').style.display = 'none';
	}
}

TWError.prototype.SetTitle = function(title)
{
	this.title = title;
	this.Create();

}

TWError.prototype.SetMessageArray = function(message_array)
{
	this.message_array = message_array;
	this.Create();
}
TWError.prototype.AddMessage = function(message)
{
	this.message_array.push(message);
	this.Create();
}
TWError.prototype.ClearMessageArray = function(message)
{
	this.message_array = new Array();
	this.Create();
}
TWError.prototype.GetErrorMessageCount = function()
{
	return this.message_array.length;
}