var BUBBLE_HTML = '<div class="bubble hidden"><div class="bubble-tip"></div><div class="bubble-envelop"><div class="bubble-close"><a href="#" onclick="closeMe(this);return false;"><img src="/images/closeMe.png" /></a></div><div class="bubble-body"></div></div></div>';
var MSIE6 = jQuery.browser.msie && jQuery.browser.version.substr(0,1) <= 6;

function urlencode (clearString) {
  var output = '';
  var x = 0;
  clearString = clearString.toString();
  var regex = /(^[a-zA-Z0-9_.]*)/;
  while (x < clearString.length) {
    var match = regex.exec(clearString.substr(x));
    if (match != null && match.length > 1 && match[1] != '') {
    	output += match[1];
      x += match[1].length;
    } else {
      if (clearString[x] == ' ')
        output += '+';
      else {
        var charCode = clearString.charCodeAt(x);
        var hexVal = charCode.toString(16);
        output += '%' + ( hexVal.length < 2 ? '0' : '' ) + hexVal.toUpperCase();
      }
      x++;
    }
  }
  return output;
}


function truncate(string, size)
{
	return string.length < size ? string : string.substr(0, size-2) + '...';
}

function placeBubble(bubbleExpr, triggerExpr)
{
	var bubble = jQuery(bubbleExpr);
	var tip = bubble.find('.bubble-tip');
	var page = jQuery('body');
	var trigger = jQuery(triggerExpr);
	var bubbleLeft = trigger.offset().left + trigger.width()/2 - bubble.width()/2;
	if (bubbleLeft < page.offset().left)
	{
		bubbleLeft = page.offset().left;
	}
	else if (bubbleLeft + bubble.width() > page.offset().left + page.width())
	{
		bubbleLeft = page.offset().left + page.width() - bubble.width();
	}
	var bubbleTop = trigger.offset().top + trigger.height() + 5;
	
	bubble
	.css('left', bubbleLeft)
	.css('top', bubbleTop)
	;
	
	tip.css('left', trigger.offset().left + trigger.width()/2 - bubbleLeft - 10);

} 

function adjustBubblePosition(bubbleExpr)
{
	var bubble = jQuery(bubbleExpr);
	var page = jQuery('body');
	var tip = bubble.find('.bubble-tip');
	var tipLeft = tip.offset().left;
	var bubbleLeft = bubble.offset().left;
	
	if (bubbleLeft < page.offset().left)
	{
		bubbleLeft = page.offset().left;
	}
	else if (bubbleLeft + bubble.width() > page.offset().left + page.width())
	{
		bubbleLeft = page.offset().left + page.width() - bubble.width();
	}
	
	bubble.css('left', bubbleLeft);
//	tip.css('left', tipLeft);
}

function centerOnScreen(bubble)
{
	var jqBubble = jQuery(bubble);
	
    var winH = jQuery(window).height();
    var winW = jQuery(window).width();
    var centerDiv = jQuery(bubble);
    centerDiv.css('top', winH/2-centerDiv.height()/2);
    centerDiv.css('left', winW/2-centerDiv.width()/2); 
}

function closeMe(button)
{
	unmountCurtain();
	jQuery(button).parents('.bubble').slideUp('fast');
}

function showHelp(trigger, text)
{
	var bubble = jQuery('#help-bubble');
	if (bubble.length == 0)
	{
		bubble = jQuery(BUBBLE_HTML).attr('id', 'help-bubble').appendTo('body');
	}
	bubble.find('.bubble-body').text(text);
	placeBubble(bubble, trigger);
	bubble.slideDown('fast', 
		function(){
			setTimeout(function(){
				bubble.slideUp('fast');
			}, 5000);
		});
}

function ajaxSubmit2(trigger)
{
	var t = jQuery(trigger);
	var form = t.is('form') ? t : t.parents('form');
	jQuery.ajax({
			url: jQuery(form).attr('action'),
			type: "POST",
			data: jQuery(form).serialize(),
			dataType: 'json',
			success:function(data)
			{
				var html = data['html'];
				if (html)
				{
					jQuery(form).parent().html(html);
				}
				var js = data['js'];
				if (js)
				{
					eval(js);
				}
			}
		});
	return false;
}

function mountCurtain()
{
	var curtain = jQuery('.curtain');
	if (!curtain.length)
	{
		curtain = 
			jQuery('<div>')
			.addClass('curtain hidden')
			.css('opacity', '0.5')
			.appendTo('body');

		jQuery(window).resize(resizeCurtain);
	}
	resizeCurtain();
	curtain.show();
}

function resizeCurtain()
{
	var body = jQuery('body');
	jQuery('.curtain').width(body.width()).height(body.height());
}

function unmountCurtain()
{
	jQuery('.curtain').hide();
}

function masterDetail(masterId, detailId)
{
	masterDetailUpdate(masterId, detailId);
	jQuery('#'+masterId).change(function(){masterDetailUpdate(masterId, detailId);});
}

function masterDetailUpdate(masterId, detailId)
{
	var qMaster = jQuery('#'+masterId);
	var qDetail = jQuery('#'+detailId);
	
	var tree = window[detailId + 'Tree'];
	var options = '';
	var branch = tree[qMaster.attr('value')];
	var selectedId = qDetail.attr('value');
	for (id in branch)
	{
		options += '<option value="' + id + '"'
		if (id == selectedId) options +=' selected="selected"' 
		options +='>' + branch[id] + '</option>';
	}
	qDetail.html(options);
	qDetail.sortOptions();
	qDetail.selectOptions(selectedId);
	
}


function promptOrderCompany(trigger)
{
	placeBubble('#order-company-bubble', trigger);
	jQuery('#order-company-bubble').slideToggle('fast');
}

function popupContact(trigger)
{
	if (window.pendingChanges)
	{
		popupEditContact(trigger);
	}
	else
	{
		visualizeContact(trigger);
	}
}

function visualizeContact(trigger)
{
	mountCurtain();
	var box = jQuery(trigger).parents('.contactBox');
	var id = contactIdOf(box);
	ajaxBubble(trigger, '#view-contact-bubble', '/contact/ajax-view?id=' + id, false, 
	function(){
			bubble = jQuery('#view-contact-bubble');
			var loadedName = bubble.find('.contactName');
			if (loadedName.length)
			{
				box.find('.contactName').text(truncate(loadedName.text(), 30));
			}
			var loadedTitle = bubble.find('.contactShortJobTitle');
			if (loadedTitle.length)
			{
				box.find('.contactJobTitle').text(truncate(loadedTitle.text(),30));
			}
	}); 
}

function editContact(trigger, id)
{
	ajaxBubble(trigger, '#view-contact-bubble', '/contact/ajax-edit-form?id=' + id, true); 
}

function popupSelfEdit(trigger, id)
{
	ajaxBubble(trigger, '#self-edit-bubble', '/contact/ajax-self-edit?id=' + id, false); 
}

function popupEditContact(trigger)
{
	var box = jQuery(trigger).parents('.contactBox');
	var id = contactIdOf(box);
	ajaxBubble(trigger, '#view-contact-bubble', '/contact/ajax-edit-form?id=' + id, false); 
}

function showAddContactBubble(trigger)
{
	var bubble = jQuery('#add-contact-bubble');
	bubble.find('input[@name="firstName"], input[@name="lastName"], input[@name="jobTitle"], input[@name="email"]')
		.attr('value', '');
	placeBubble(bubble, trigger);
	bubble.slideDown('fast');
}

function showEditCompanyBubble(trigger, companyId)
{
	ajaxBubble(trigger, '#edit-company-bubble', '/company/ajax-edit-form?id=' + companyId);  
}

function showCompanyHistory(trigger, companyId)
{
	ajaxBubble(trigger, '#company-history-bubble', '/company/ajax-history?id=' + companyId);  
}

function showCompanyDeleted(trigger, companyId)
{
	ajaxBubble(trigger, '#company-history-bubble', '/company/ajax-view-deleted?id=' + companyId);  
}

function ajaxBubble(trigger, bubble, url, skipPlacing, callback)
{
	var jqBubble = jQuery(bubble);
	if (jqBubble.length == 0)
	{
		var shellHtml = jsTemplates['bubble'];
		jqBubble = jQuery(shellHtml).attr('id', bubble.substr(1)).appendTo('body');
	}
	jqBubble.find('.bubble-body').html('<span class="processing">Loading...</span>');
	if (!skipPlacing)
	{
		if (trigger) placeBubble(jqBubble, trigger);
		else centerOnScreen(jqBubble);
	}
	jqBubble.slideDown('fast');
	
	jQuery.ajax({
			url: url,
			type: 'GET',
			dataType: 'html',
			success:function(html)
			{
				jqBubble.find('.bubble-body').html(html);
				adjustBubblePosition(jqBubble);
				if (callback) callback();
			},
			error:function()
			{
				jqBubble.find('.bubble-body').html('Error :-(');
			}
	});
}

function contactIdOf(box)
{
	return jQuery(box).attr('id').substr('contact-'.length);
} 

function unformatNumber(number)
{
	return number.replace(/[.,M ]/g, '');
}

var REMOVE_LINK_HANDLE = '<div class="removeLinkDiv hidden"><img class="middle linkHandle" src="/images/linkHandle.png" border="0"/></div>';
var LINK_HANDLE = '<div class="linkHandleDiv"><img class="middle linkHandle" src="/images/linkHandle.png" border="0"/></div>';

function initOrgChartEditor()
{
	window.orgChartEditable = true;
}

function initDynamics()
{
	initContactBoxDynamics(jQuery('.contactBox'));
	
	var hash = window.location.hash;
	if (hash != '')
	{
		var box = jQuery('#contact-' + hash.substr(1));
		if (box.length > 0)
		{
			box.addClass('hover');
			setTimeout(function(){box.removeClass('hover');}, 20000);
		}
	}
	
	if (window.orgChartEditable)
	{
		jQuery('#executivePane, #managementPane, #boardPane').droppable({
			hoverClass: 'columnArmed',
			drop: orgChartInsert,
			accept: function(draggable){return draggable.hasClass('contactBox');},
			tolerance: 'intersect'
		});
		jQuery('#ceoPane').droppable({
			hoverClass: 'ceoArmed',
			drop: orgChartReplaceCeo,
			accept: function(draggable){return draggable.hasClass('contactBox');},
			tolerance: 'intersect'
		});
	}
}

function initContactBoxDynamics(set)
{
	set.hover(
		function()
		{
			jQuery(this).addClass('hover');
			jQuery(this).find('.removeLinkDiv').show();
			if (jQuery(this).parents('#ceoPane').length > 0)
			{
				jQuery('#executivePane .contactBox').addClass('hover');
			}
			else
			{
				var childIds = window.inversedLinks[contactIdOf(this)];
				for (var i in childIds)
				{
					if (!isNaN(parseInt(i))) // fix of the ugly Mootools bug that adds tons of fucking shit to each and every array
					{
						var child = jQuery('#contact-' + childIds[i]); 
						child.addClass('hover');
						child.find('.removeLinkDiv').show();
					}
				}
			}
		},
		function()
		{
			jQuery(this).removeClass('hover');
			jQuery(this).find('.removeLinkDiv').hide();
			if (jQuery(this).parents('#ceoPane').length > 0)
			{
				jQuery('#executivePane .contactBox').removeClass('hover');
			}
			else
			{
				var childIds = window.inversedLinks[contactIdOf(this)];
				for (var i in childIds)
				{
					if (!isNaN(parseInt(i))) // fix of the ugly Mootools bug that adds tons of fucking shit to each and every array
					{
						var child = jQuery('#contact-' + childIds[i]); 
						child.removeClass('hover');
						child.find('.removeLinkDiv').hide();
					}
				}
			}
		}
	);
	
	if (window.orgChartEditable)
	{
		set.draggable({
			handle: '.handle',
			helper: 'clone',
			revert: true,
			opacity: 0.5,
			zIndex: 5,
			containment: '#contactChart',
			start: orgChartStartDrag,
			stop: function(){jQuery(this).show()}
		});
		
		set.find('.linkHandle').draggable({
			helper: function(){return jQuery(this).clone().appendTo('body');}, // avoid disappearing on mouseover
			revert: true,
			zIndex: 5,
			containment: '#contactChart'
		});
		
		set.find('.removeLinkDiv').click(function(){
			orgChartRemoveLink(this);
		});
		
		set.droppable({
			hoverClass: 'armed',
			accept: function(draggable){return this.parents('#executivePane').length && draggable.hasClass('linkHandle');},
			drop: orgChartLink,
			tolerance: 'intersect'
		});
		
		set.find('.dndHover').each(function(){
			jQuery(this).hover(
				function(){
					jQuery(this).attr('src', '/images/dndBlue.png');
				},
				function(){
					jQuery(this).attr('src', '/images/dnd.png');
				}
			);
			jQuery(this).mousedown(function(){jQuery(this).attr('src', '/images/dndWhite.png');});
			jQuery(this).mouseup(function(){jQuery(this).attr('src', '/images/dndBlue.png');});
		});		
		
		set.find('.magnifyHover').each(function(){
			jQuery(this).hover(
				function(){
					jQuery(this).attr('src', '/images/magnifyBlue.png');
				},
				function(){
					jQuery(this).attr('src', jQuery(this).hasClass('dark')? '/images/magnifyDark.png' : '/images/magnifyLight.png');
				}
			);
			jQuery(this).mousedown(function(){jQuery(this).attr('src', '/images/magnifyWhite.png');});
			jQuery(this).mouseup(function(){jQuery(this).attr('src', '/images/magnifyBlue.png');});
		});		
	}	
}

function destroyDynamics()
{
	jQuery('.contactBox').unbind('mouseenter mouseleave');
	if (window.orgChartEditable)
	{
		jQuery('.contactBox').draggable('destroy');
		jQuery('#executivePane, #managementPane, #boardPane').droppable('destroy');
		jQuery('#ceoPane').droppable('destroy');
		jQuery('.linkHandle').draggable('destroy');
		jQuery('.contactBox').droppable();
	}		
}

function initOrgChart()
{
	jQuery(function(){
		calculateInversedLinks();	
		redrawLinks();		
		adjustHeight();
		initDynamics();		
		initImageHovers();
		initToolbarButtonHovers();
		initEmailAssistant('#email', '#firstName',  '#lastName', '#company-url');
		jQuery('#jobTitleFilter').keyup(onFilterChange);
		jQuery('#subsidiaries-trigger').click(showSubsidiaries);
	});
	
//	if (!MSIE6)
	{
		jQuery(window).resize(function(){
			removeLinks();
			
			setTimeout(function(){
				redrawLinks();
				adjustHeight();
				}, 500);
			});
	}

}	

function showSubsidiaries()
{
	var bubble = jQuery('#subsidiaries-bubble');
	placeBubble(bubble, '#subsidiaries-trigger');
	bubble.slideToggle('fast');
}

function initEmailAssistant(email, firstName, lastName, url)
{
	jQuery(email).keyup(function(e){
		if (e.which==113) //F2
		{
			var $url = jQuery(url);
			var domain = $url[0].tagName == 'INPUT' ? $url.val() : $url.text(); 
			var domain = jQuery.trim(domain);
			if (domain.substr(0,4) =='www.') domain = domain.substr(4);
			jQuery(email).val(purifyForEmail(jQuery(firstName).val()) + '.' + purifyForEmail(jQuery(lastName).val()) + '@' + domain);
			e.stopPropagation(); e.preventDefault();
		}
	})
}

function purifyForEmail(s)
{
	var norm = new Array('À','Á','Â','Ã','Ä','Å','Æ','Ç','È','É','Ê','Ë','Ì','Í','Î','Ï',
			'Ð','Ñ','Ò','Ó','Ô','Õ','Ö','Ø','Ù','Ú','Û','Ü','Ý','Þ','ß', 
			'à','á','â','ã','ä','å','æ','ç','è','é','ê','ë','ì','í','î','ï','ð','ñ', 
			'ò','ó','ô','õ','ö','ø','ù','ú','û','ü','ý','ý','þ','ÿ',"'", ' ');
	var spec = new Array('A','A','A','A','A','A','A','C','E','E','E','E','I','I','I','I',
			'D','N','O','O','O','0','O','O','U','U','U','U','Y','b','s', 
			'a','a','a','a','a','a','a','c','e','e','e','e','i','i','i','i','d','n', 
			'o','o','o','o','o','o','u','u','u','u','y','y','b','y', '', '');
	for (var i = 0; i < spec.length; i++)
		s = replaceAll(s, norm[i], spec[i]);
	return s;
}

//Remplace toutes les occurences d'une chaine
function replaceAll(str, search, repl) {
while (str.indexOf(search) != -1)
str = str.replace(search, repl);
return str;
}

function initImageHovers()
{
	jQuery('.imagehover').hover(
		function(){
			var src = jQuery(this).attr('src');
			if (src.indexOf('-hover') == -1)
			{
				var newSrc = src.replace('.png', '-hover.png');
				jQuery(this).attr('src', newSrc);
			}
		},
		function(){
			var src = jQuery(this).attr('src');
			if (src.indexOf('-hover') != -1)
			{
				var newSrc = src.replace('-hover', '');
				jQuery(this).attr('src', newSrc);
			}
		}
		
	);
}

function calculateInversedLinks()
{
	// prepare inversed links array.
	var inversedLinks = [];
	for(var childId in window.contactLinks)
	{
		if (!isNaN(parseInt(childId))) // fix of the ugly Mootools bug that adds tons of fucking shit to each and every array
		{
			var parentId = window.contactLinks[childId];
			if (typeof inversedLinks[parentId] == 'undefined')
			{
				inversedLinks[parentId] = new Array();
			} 
			inversedLinks[parentId][inversedLinks[parentId].length] = childId;
		}
	}
	
	window.inversedLinks = inversedLinks;
}

function onFilterChange()
{
	if (window.filterTimeout)
	{
		clearTimeout(window.filterTimeout);
	}
	
	window.filterTimeout = setTimeout(refilterOrgChart, 300);
}

function refilterOrgChart()
{
	removeLinks();
	var pattern = jQuery('#jobTitleFilter').attr('value');
	jQuery('.contactBox').each(function(){
		var jobTitle = jQuery(this).find('.contactJobTitle');
		var jtText = jobTitle.text();
		var name = jQuery(this).find('.contactName');
		var nameText = name.text();
		if (pattern == '')
		{
			jobTitle.text(jtText); // remove html formatting
			name.text(nameText); // remove html formatting
			jQuery(this).show();
		}
		else
		{
			var regexp = new RegExp(pattern, 'i');
			var jtPos = jtText.search(regexp);
			var namePos = nameText.search(regexp);
			if (jtPos == -1 && namePos == -1)
			{
				jQuery(this).hide();
			} 
			else
			{
				if (jtPos != -1)
				{
					var jtHtml = colorize(jtText, jtPos, pattern); 
					jobTitle.html(jtHtml);
				}
				else
				{
					jobTitle.text(jtText);
				}
				
				if (namePos != -1)
				{
					var nameHtml = colorize(nameText, namePos, pattern); 
					name.html(nameHtml);
				}
				else
				{
					name.text(nameText);
				}
					
				jQuery(this).show();
			}
		}
	});
	setTimeout(redrawLinks, 500);
}

function colorize(jtText, pos, pattern)
{
	var result =
	jtText.substring(0, pos) 
	+ '<span class="red">' +
	jtText.substring(pos, pos + pattern.length) 
	+ '</span>' +
	jtText.substring(pos + pattern.length, jtText.length);
	
	return result; 
}

function orgChartStartDrag()
{
	jQuery(this).hide();
}

function orgChartInsert(e, ui)
{
	var draggable = jQuery(ui.draggable);
	var helper = jQuery(ui.helper);
	var wasCeo = draggable.parent().attr('id') == 'ceoPane';
	var wasManager = draggable.parent().attr('id') == 'managementPane';
	var draggableTop = helper.offset().top;
//	var columnTop = jQuery(this).offset().top;
//	var index = Math.ceil((draggableTop - columnTop) / 58);

	helper.remove();
	draggable.css('opacity', 1.).removeClass('hi');
	
	// !!!!! Use clone, otherwise serious problems in IE6 :(
	
	var sibling = null;
	
	jQuery(this).children().each(function(){
		if (sibling == null && jQuery(this).offset().top > draggableTop && jQuery(this).css('display') != 'none')
		{
			sibling = this;
		}
	});
	
	if (sibling!= null)
	{
		draggable.insertBefore(sibling);
	}
	else
	{
		draggable.appendTo(this);
	}
	
	if (wasCeo)
	{
		jQuery('#ceoPane').empty().append(jQuery('<div>').addClass('contactBoxEnigmatic'));
	}
	draggable.slideDown('fast', function(){
		adjustHeight();
		redrawLinks();
	});
	
	var newLevel = 0;
	switch(jQuery(this).attr('id'))
	{
		case 'ceoPane':
			newLevel = 1;
			break;
		case 'boardPane':
			newLevel = 2;
			break;
		case 'executivePane':
			newLevel = 3;
			break;
		case 'managementPane':
		default:
			newLevel = 4;
			break;
	}
	
	if (jQuery(this).attr('id') == 'managementPane')
	{
		if (!wasManager)
		{
			var contactId = contactIdOf(draggable);
			draggable.prepend(window.contactLinks[contactId] ? REMOVE_LINK_HANDLE : LINK_HANDLE);
			jQuery('.linkHandle').draggable({
				helper: 'clone',
				revert: true,
				zIndex: 5,
				containment: '#contactChart'
			});
		}		
	}
	else
	{
		draggable.children('.linkHandleDiv, .removeLinkDiv').remove();
	}
	
	processMoveContact(draggable, newLevel);
	return true;
}

function processMoveContact(contactBox, level)
{
	orgChartPendingChanges(true);

	var id = contactIdOf(contactBox);
	jQuery(contactBox).addClass('processing');
	jQuery.ajax({
		type:'GET',
		url:'/contact/move',
		data:'id='+id+'&level='+level,
		success:function(){jQuery(contactBox).removeClass('processing');}
	});
}

function processCreateLink(fromBox, toBox)
{
	orgChartPendingChanges(true);

	var fromId = contactIdOf(fromBox);
	var toId = contactIdOf(toBox);

	jQuery.ajax({
		type:'GET',
		url:'/contact/link',
		data:'child='+fromId+'&parent='+toId,
		success:function(){jQuery(toBox).removeClass('processing');}
	});
}

function processRemoveLink(childBox)
{
	orgChartPendingChanges(true);

	var childId = contactIdOf(childBox);

	jQuery.ajax({
		type:'GET',
		url:'/contact/link',
		data:'child='+childId,
		success:function(){jQuery(childBox).removeClass('processing');}
	});
}

function orgChartReplaceCeo(e, ui)
{
	var draggable = jQuery(ui.draggable);
	var helper = jQuery(ui.helper);
	var wasCeo = draggable.parent().attr('id') == 'ceoPane';
	if (wasCeo) return;
	
	helper.remove();

	var existingCeo = jQuery('#ceoPane').children('.contactBox');
	if (existingCeo.length)
	{
		existingCeo.removeClass('hi').hide().prependTo('#boardPane').slideDown('fast');
		processMoveContact(existingCeo, 2, 'F');	
	}

	jQuery(this).empty();
	draggable.children('.linkHandleDiv, .removeLinkDiv').remove();
	draggable.addClass('hi').appendTo(this).show('fast', function(){redrawLinks();});
	
	processMoveContact(draggable, 1, 'F');	
	
}

function contactUpdated(id, name, jobTitle)
{
	orgChartPendingChanges(true);
	
	var box = jQuery('#contact-' + id);
	box.find('.contactName').text(truncate(name, 30));
	box.find('.contactJobTitle').text(truncate(jobTitle, 30));
	unmountCurtain();
	jQuery('#view-contact-bubble').slideUp('fast');
}

function selfUpdated(id, name, jobTitle)
{
	var box = jQuery('#contact-' + id);
	box.find('.contactName').text(name);
	box.find('.contactJobTitle').text(jobTitle);
	jQuery('#self-edit-bubble').slideUp('fast');
}

function contactDeleted(id)
{
	orgChartPendingChanges(true);
	
	var box = jQuery('#contact-' + id);
	unmountCurtain();
	jQuery('#view-contact-bubble').slideUp('fast');
	box.slideUp('fast', function(){
		box.remove();
		redrawLinks();
	});
}

function selfDeleted(id)
{
	var box = jQuery('#contact-' + id);
	jQuery('#self-edit-bubble').slideUp('fast');
	box.slideUp('fast', function(){
		box.remove();
	});
}

function companyUpdated(values)
{
	orgChartPendingChanges(true);
	jQuery('#edit-company-bubble').slideUp('fast');
	jQuery('#company-info h1').text(values.name);
	jQuery('#company-info .industry').text(values.industry);
	jQuery('#company-info .url').html('<a href="http://' + values.url + '" target="_blank">' + values.url + '</a>');
	jQuery('#company-info .parent').html('<a href="/company/view?id=' + values.parentId + '">' + values.parent + '</a>');
}

function contactAdded(id, name, shortJobTitle, jobTitle, companyCount)
{
	orgChartPendingChanges(true);
	jQuery('#add-contact-bubble').slideUp('fast');

	var html = '<div title="' + jobTitle + '" id="contact-' + id + '" class="contactBox hidden">'
	+ 	'<div class="contactPad">';
	if (companyCount > 1)
	{
		html += '<div class="contactVcards">'
	  		+ '<img class="middle" src="/images/vcards.gif" border="0"/>'
	  		+ ' ' + companyCount
	  		+ '</div>';
	}
	html += '<div class="contactJobTitle">' + shortJobTitle + '</div>'
	+ 		'<div class="contactAction"><img border="0" src="/images/dnd.png" class="middle handle dndHover"/>'
	+ 		' <a onclick="popupContact(this);return false;" href="#">'
	+ 			'<img border="0" src="/images/magnify.png" class="middle magnifyHover"/></a>'
	+ 		'</div><div class="contactName">' + name + '</div></div></div>';
	
	jQuery(html).prependTo('#managementPane');
	var cb = jQuery('#contact-' + id );
	initContactBoxDynamics(cb);
	cb.prepend(LINK_HANDLE);
	cb.find('.linkHandle').draggable({
		helper: 'clone',
		revert: true,
		zIndex: 5,
		containment: '#contactChart'
	});
	cb.addClass('redBox');

	cb.slideDown('fast', function(){
		var bubble = jQuery('#new-contact-bubble');
		placeBubble(bubble, cb.find('.handle'));
		bubble.slideDown('fast');
		setTimeout(function()
		{
			bubble.slideUp('fast', function(){cb.removeClass('redBox');});	
		}, 5000);		
		redrawLinks();
	});
	
	
}

function promptSavePending(companyId)
{
	if (jQuery('#validation-checkbox').attr('checked'))
	{
		unblockPageTransition();
		document.location.href=	'/company/apply-pending?id=' + companyId; 
	}
	else
	{
		promptValidatePending();
	}
}

function promptValidatePending()
{
	var bubble = jQuery('#prompt-validate-bubble')
	if (jQuery('#validation-checkbox').attr('checked'))
	{
		bubble.slideUp('fast');
	}
	else
	{
		placeBubble(bubble, '#validation-checkbox');
		bubble.slideDown('fast');
	}	
}

function orgChartLink(e, ui)
{
	try
	{
		var draggable = jQuery(ui.draggable);
		var fromBox = draggable.parents('.contactBox');
		var helper = jQuery(ui.helper);
		draggable.parents('.linkHandleDiv').replaceWith(REMOVE_LINK_HANDLE);
		helper.remove();
		jQuery(this).addClass('processing');
		jQuery(fromBox).removeClass('highlighted');
	
		var fromId = contactIdOf(fromBox);
		var toId = contactIdOf(this);
		window.contactLinks[fromId] = toId;
		
		processCreateLink(fromBox, this);
		calculateInversedLinks();
		redrawLinks();
	}
	catch(e){}
	
}

function orgChartRemoveLink(handle)
{
	var box = jQuery(handle).parents('.contactBox');
	var contactId = contactIdOf(box);
	box.removeClass('highlighted').addClass('processing');
	
	window.contactLinks[contactId] = null;
	
	jQuery(handle).parents('.removeLinkDiv').replaceWith(LINK_HANDLE);

	jQuery('.linkHandle').draggable({
		helper: 'clone',
		revert: true,
		zIndex: 5,
		containment: '#contactChart'
	});
	calculateInversedLinks();
	redrawLinks();

	processRemoveLink(box);
		
}

function orgChartDrawLink(canvas, left, top, from, to)
{
	var jqFrom = jQuery(from); 
	var jqTo = jQuery(to);
	if (!jqFrom.length || !jqTo.length) return;
	if (jqFrom.css('display') == 'none' || jqTo.css('display') == 'none') return; 
	
	var fromX = jqFrom.offset().left + jqFrom.outerWidth();
	var fromY = jqFrom.offset().top + jqFrom.outerHeight()/2;
	
	var toX = jqTo.offset().left;
	var toY = jqTo.offset().top + jqTo.outerHeight()/2;
	
	/*
	var canvasOffset = jQuery(canvas).offset();
	jQuery(canvas).drawLine(
		fromX - canvasOffset.left, 
		fromY  - canvasOffset.top,
		toX  - canvasOffset.left,
		toY  - canvasOffset.top, {color: '#909090', stroke: 1.0});
	*/
	var x1 = fromX - left;
	var x2 = toX - left;
	var y1 = fromY - top;
	var y2 = toY - top;
	var path = "M" + x1 + " " + y1 + "L" + x2 + " " + y2;  
	canvas.path(path).attr({stroke: "#909090"});
}

function drawSecondColumnLinks()
{
	var ceoPane = jQuery('#ceoPane');
	var executivePane = jQuery('#executivePane');
	var contacts = executivePane.children('.contactBox');
	var from = ceoPane.children().eq(0);
	var toExample = contacts.eq(0);

	if (!from.length || !toExample.length) return;

	var left = from.offset().left + from.outerWidth();
	var right = toExample.offset().left;
	var top = ceoPane.offset().top;
	var bottom = executivePane.offset().top + executivePane.outerHeight();

	var canvas = recreateCanvas('canvas1', left, right, top, bottom);

	contacts.each(function(){orgChartDrawLink(canvas, left, top, from, this);});
}

function drawThirdColumnLinks()
{
	var executivePane = jQuery('#executivePane');
	var managementPane = jQuery('#managementPane');

	var contacts = managementPane.children('.contactBox');
	if (!contacts.length) return;

	var left = executivePane.offset().left + executivePane.outerWidth() - 5;
	var right = managementPane.offset().left +5;
	var top = executivePane.offset().top;
	var bottom = Math.max(
		executivePane.offset().top + executivePane.outerHeight(),
		managementPane.offset().top + managementPane.outerHeight()
		);

	var canvas = recreateCanvas('canvas2', left, right, top, bottom);

	contacts.each(function(){
		var chiId = contactIdOf(this);
		if (window.contactLinks[chiId])
		{
			var parentId = window.contactLinks[chiId];
			var parent = jQuery('#contact-' + parentId);
			if (parent.length && parent.parents('#executivePane').length) // second column only
			{
				orgChartDrawLink(canvas, left, top, parent, this);
			}
		}
		});
}


function removeCanvas(id)
{
	jQuery('#'+id).remove();
}

function recreateCanvas(id, left, right, top, bottom)
{
	removeCanvas(id);
	
	var canvas = jQuery('<div>');
	jQuery('body').append(canvas);
	canvas
		.attr('id', id)
		.css('position', 'absolute')
		.css('top', top)
		.css('height', bottom - top + 1)
		.css('left', left)
		.css('width', right - left + 1);
	
	canvas.css('z-index', 2);
//	return canvas;
	
	var raph = Raphael(canvas.get(0), right-left, bottom-top);
	raph.left = left;
	raph.top = top;
	return raph;
}

function removeLinks()
{
	removeCanvas('canvas1');
	removeCanvas('canvas2');
}

function redrawLinks()
{
//	if (MSIE6) return;

	drawSecondColumnLinks();
	drawThirdColumnLinks();
}

function adjustHeight()
{
	jQuery('#boardPane,#executivePane, #managementPane').each(function(){jQuery(this).css('height','auto');});
	var bottom = 0;
	jQuery('.contactColumn').each(function(){bottom = Math.max(bottom, jQuery(this).offset().top + jQuery(this).height());});
	jQuery('#boardPane,#executivePane, #managementPane').each(function(){var q=jQuery(this); q.height(bottom-q.offset().top-10);});	
}

function initToolbarButtonHovers ()
{
	jQuery('.toolbarButtonBoth').hover(
		function(){
			jQuery(this).find('.toolbarButtonBothLeft').addClass("hover");
			jQuery(this).find('.toolbarButtonBothMiddle').addClass("hover");
			jQuery(this).find('.toolbarButtonBothRight').addClass("hover");
		},
		function(){
			jQuery(this).find('.toolbarButtonBothLeft').removeClass("hover");
			jQuery(this).find('.toolbarButtonBothMiddle').removeClass("hover");
			jQuery(this).find('.toolbarButtonBothRight').removeClass("hover");
		}
	);
}

function orgChartSortBy(what)
{
	destroyDynamics();
	switch(what)
	{
		case 'hierarchy':
			jQuery('#sortByName').removeClass('toolbarButtonLeftSelected').addClass('toolbarButtonLeft');
			jQuery('#sortByJobTitle').removeClass('toolbarButtonMiddleSelected').addClass('toolbarButtonMiddle');
			jQuery('#sortByHierarchy').removeClass('toolbarButtonRight').addClass('toolbarButtonRightSelected');
			break;

		case 'jobTitle':
			jQuery('#sortByName').removeClass('toolbarButtonLeftSelected').addClass('toolbarButtonLeft');
			jQuery('#sortByJobTitle').removeClass('toolbarButtonMiddle').addClass('toolbarButtonMiddleSelected');
			jQuery('#sortByHierarchy').removeClass('toolbarButtonRightSelected').addClass('toolbarButtonRight');
			break;
		
		case 'name':
			jQuery('#sortByName').removeClass('toolbarButtonLeft').addClass('toolbarButtonLeftSelected');
			jQuery('#sortByJobTitle').removeClass('toolbarButtonMiddleSelected').addClass('toolbarButtonMiddle');
			jQuery('#sortByHierarchy').removeClass('toolbarButtonRightSelected').addClass('toolbarButtonRight');
			break;
	}
	
	
	if (what == 'hierarchy')
	{
		jQuery('#boardPane, #executivePane').each(function(){orgChartSortColumn(this, 'jobTitle');});
		orgChartSortManagers();
	}
	else
	{
		jQuery('#boardPane, #executivePane, #managementPane').each(function(){orgChartSortColumn(this, what);});
	}	
	initDynamics();
	redrawLinks();
}

function orgChartSortColumn(col, byWhat)
{
	var jqCol = jQuery(col);
	var jqBoxes = jqCol.find('.contactBox');
	var boxes = [];
	for (var i=0; i < jqBoxes.length; i++)
	{
		boxes.push(jqBoxes.get(i));
	}
	jqCol.empty();
	boxes.sort(function(a, b){
		var first = jQuery(a).find(byWhat == 'name' ? '.contactName' : '.contactJobTitle').text().toLowerCase();
		var second = jQuery(b).find(byWhat == 'name' ? '.contactName' : '.contactJobTitle').text().toLowerCase();
		var result = first>second ? 1 : first<second ? -1 : 0;
//		if (console) console.log(first + '/' + second + ': ' + result);
		return result;
	});
	
	for (var i = 0; i < boxes.length; i++)
	{
		jqCol.append(boxes[i]);
	}
}

function orgChartSortManagers()
{

	var jqExecutives = jQuery('#executivePane');
	var jqManagers = jQuery('#managementPane');
	
	// move everybody to the temporary dom element;
	var div = jQuery('<div>');
	jqManagers.find('.contactBox').appendTo(div);
	
	// move all linked managers linked to executives one by one;
	jqExecutives.find('.contactBox').each(function(){
		var parentId = contactIdOf(this);
		var childIds = window.inversedLinks[parentId];
		for(var i in childIds)
		{
			if (!isNaN(parseInt(i))) // fix of the ugly Mootools bug that adds tons of fucking shit to each and every array
			{
				var childId = childIds[i];
				var child = div.find('#contact-' + childId);
				child.appendTo(jqManagers);
			}
		}
	});
	
	// move all unlinked;
	div.children().appendTo(jqManagers);
	
	
}

function orgChartPendingChanges(b)
{

	if (b)
	{
		window.pendingChanges = true;
		blockPageTransition('Il y a des changements non enregistres dans l\'organigramme');
		jQuery('#validation-bar').slideDown('fast', function(){redrawLinks();});
//		jQuery('#validation-bar').show();redrawLinks();
	}
	else
	{
		window.pendingChanges = false;
		unblockPageTransition();
		jQuery('#validation-bar').slideUp('fast', function(){redrawLinks();});
//		jQuery('#validation-bar').hide();redrawLinks();

	}
	
}

function blockPageTransition(text)
{
	window.onbeforeunload = function(){return text;};
}

function unblockPageTransition()
{
	window.onbeforeunload = null;
}

function orgChartReload()
{
	unblockPageTransition();
	document.location.reload();
}


function filterCountry(country)
{
	jQuery('#advanced-search-form').find('input[@name="country"]').attr('value', country);
	jQuery('#search-offset').attr('value', 0);
	jQuery('#advanced-search-form').submit();
}

function filterIndustry(industry)
{
	jQuery('#advanced-search-form').find('input[@name="industry"]').attr('value', industry);
	jQuery('#search-offset').attr('value', 0);
	jQuery('#advanced-search-form').submit();
}


function alertDelete(trigger)
{
	var tr = jQuery(trigger).parents('tr');
	var id = tr.attr('id').substr('row-'.length);
	jQuery.ajax({
		type:'GET',
		url:'/alert/delete',
		data:'id='+id,
		success:function(){tr.fadeOut('fast');}
	});
}


function tBubble(trigger, template)
{
	var id = 'bubble-' + template;
	var bubble = jQuery('#'+id);
	if (bubble.length == 0)
	{
		var shellHtml = jsTemplates['bubble'];
		bubble = jQuery(shellHtml).attr('id', id).appendTo('body');
	}
	var content = jsTemplates[template];
	bubble.find('.bubble-body').html(content);
	placeBubble(bubble, trigger);
	bubble.slideDown('fast');
}

function fillUrl(target)
{
	var url = window.location.href;
	jQuery(target).parents('form').andSelf().find('input[@name="url"]').attr('value', url);
}

function initAddCompany()
{
	initIncome();
	initEmailAssistant('#email', '#firstName',  '#lastName', '#url');	
}

function initIncome()
{
	var radios = jQuery('#add-company-form, #edit-company-form').find('input[@name="incomeSufficient"]');
	radios.change(function()
	{
		if (jQuery(this).attr('checked'))
		{
			if (jQuery(this).attr('value') == 0)
			{
				tBubble(this, 'insufficientIncome');
			}
			else
			{
				jQuery('#bubble-insufficientIncome').slideUp('fast');
			}
		}
	});
}

function checkIncome(target)
{
	var radios = jQuery('#add-company-form, #edit-company-form')
	.find('input[@name="incomeSufficient"]');
	for (var i=0; i < radios.length; i++)
	{
		var radio = jQuery(radios.get(i));
		if (radio.attr('value') == 1 && !radio.attr('checked'))
		{
			tBubble(target, 'insufficientIncome');
			return false;
		}
	}
	return true;
}

function falseFunc()
{
	return false;
}


function thatsMe(button, yes)
{
	var row = jQuery(button).parents('tr');
	var id = row.attr('id').substr('contact-'.length);
	ajaxBubble(button, '#certify-thats-me-bubble', '/user/certify-thats-me?id=' + id + '&yes=' + yes, false); 
}

function thatsMeCertified(homoId, yes)
{
	jQuery.ajax({
			url: '/user/thats-me',
			type: "POST",
			data: 'contactId=' + homoId + '&yes=' + yes,
			dataType: 'html',
			success:function(data)
			{
				jQuery('#contact-'+homoId).find('.homonymActions').html(data);
				jQuery('#certify-thats-me-bubble').slideUp('fast');
			}
		});
	return false;
}


function promptHomonyms(trigger)
{
	if (window.promptHomonymsTimeout)
	{
		clearTimeout(window.promptHomonymsTimeout);
	}
	window.promptHomonymsTimeout = setTimeout(function(){doPromptHomonyms(trigger);}, 300);
}

function doPromptHomonyms(trigger)
{
	var firstName = jQuery(trigger).parents('form').find('input[@name="firstName"]').attr('value');
	var lastName = jQuery(trigger).parents('form').find('input[@name="lastName"]').attr('value');
	jQuery.ajax({
		url: '/contact/prompt-homonyms',
		type: 'GET',
		data: 'first=' + firstName + '&last=' + lastName,
		dataType: 'html',
		success:function(html)
		{
			jQuery('#homo-prompt').html(html);
		},
		error:function()
		{
			jQuery('#homo-prompt').html('');
		}
	});
}

function openContributions()
{
	jQuery('.openContribution').each(function(){
		var row = jQuery(this).parents('tr');
		var id = row.attr('id').substr('history-'.length);
		ajaxBubble(this, '#view-history', '/user/ajax-history-view?id=' + id);
	});
}

function setSearchOption(trigger, option)
{
	var form = jQuery(trigger).parents('form');
	form.find('input[@name="option"]').attr('value', option);
	form.find('.option').each(function(){
		if (this == trigger)
		{
			jQuery(this).parents('li').addClass('selected');
		}
		else
		{
			jQuery(this).parents('li').removeClass('selected');
		}
	});
	
	jQuery('.search-example').each(function(){
		if (jQuery(this).attr('id') == "home-search-example-" + option)
		{
			jQuery(this).removeClass('hidden');
		}
		else
		{
			jQuery(this).addClass('hidden');
		}
	});	
}

function more(trigger, onoff)
{
	var more = jQuery(trigger).parents('.moreless').find('.more');
	var less = jQuery(trigger).parents('.moreless').find('.less');
	if (onoff) //show
	{
		more.show();
		less.hide();
	}
	else
	{
		more.hide();
		less.show();
	}
}

function reloadMessageSubject()
{
	var lang = jQuery('#lang').val();
	var selection = jQuery('#subjectType').val();  
	jQuery('#subjectType').replaceWith('<img id="subjectType" src="/images/ajax-loader.gif">');
	jQuery.ajax({
		url: '/message/ajax-subject',
		type: "GET",
		data: {lang: lang},
		dataType: 'html',
		success: function(data)
		{
			jQuery('#subjectType').replaceWith(data);
			jQuery('#subjectType').val(selection);
		}
	});
}

try {
  document.execCommand("BackgroundImageCache", false, true);
} catch(err) {}
