var AgregatorObj;

function Agregator()
{
	// hashtable of arrays
	var Agregates ;
	// no way to parse this dynamic hashtable !!! => using AgregateNames
	// keys of the previous hashtable
	var AgregateNames ;
	// hashtable with key = agregate name, value = agregate id (num)
	var AgregateIds ;
	// current aggregate name
	var CurrentAgregName ;
	// number of agregates
	var AgregateNum ;
	
	this.Agregates = new Hash() ;
	this.AgregateNames = new Array() ;
	this.AgregateIds = new Hash() ;
	this.AgregateNum = 0 ;
	this.CurrentAgregName = '' ;
	
	AgregatorObj = this ;
}

Agregator.prototype = {
	GetParentAgregate : function(ps_Expr)
	{
		for(j = 0 ; j < this.AgregateNames.length ; j++)
		{
			if(this.AgregateNames[j] == null)
				continue;
				
			if(this.Agregates[ this.AgregateNames[j] ] == null)
				continue ;
				
			for(i = 0 ; i < this.Agregates[ this.AgregateNames[j] ].length ; i++)
			{
				if(this.Agregates[ this.AgregateNames[j] ][i] == ps_Expr)
					return this.AgregateNames[j] ;
			}
		}
		
		return '' ;
	}
	,
	LitTagsWithAtLeastOneKwInCommon : function(ps_SelectedWord)
	{
		var a_Tags = $$('#MainTC a') ;
		var a_Result = [] ;
		
		a_Tags.each(function(Tag)
		{
			if((ps_SelectedWord != Tag.innerHTML) && (AgregatorObj.HasAWordInCommon(ps_SelectedWord, Tag.innerHTML) != null))
				a_Result.push(Tag.id) ;
		});
		
		a_Result.each(function(TagId)
		{
			$(TagId).addClassName('TagWithWordInCommon') ;
		});
	}
	,
	HasAWordInCommon : function(ps_Word1, ps_Word2)
	{
		var reg_Split = new RegExp("[\\s\\b_]+", "g") ;
		var a_Word1Parts = ps_Word1.split(reg_Split) ;
		var s_RegWordParts = '' ;
		a_Word1Parts.each(function(s_Part)
		{
			s_RegWordParts += "\\b" + s_Part + "\\b|" ;
		}) ;
		// alert("s_RegWordParts="+s_RegWordParts);
		s_RegWordParts = s_RegWordParts.substr(0, s_RegWordParts.length - 1) ;
		var reg_WordParts = new RegExp(s_RegWordParts,"gi") ;
		return ps_Word2.match(reg_WordParts) ;
	}
	,
	AddAgregate : function()
	{
		// alert("AddAgregate: "+TagHandleObj.CurTagId) ;
		// check whether the agregate does not already exist
		var CurTag = $(TagHandleObj.CurTagId) ;
		
		if(this.Agregates[ CurTag.innerHTML ] != null)
		{
			// alert($(TagHandleObj.CurTagId).innerHTML + " existe deja") ;
			this.SelectAgregate(CurTag.innerHTML) ;
			return ;
		}
		
		// get keywords of the tag & update structures (agregates, agregate names & agregate ids)
		this.CurrentAgregName = CurTag.innerHTML ;
		this.Agregates[ this.CurrentAgregName ] = new Array( this.CurrentAgregName );
		
		this.AgregateNames.push(this.CurrentAgregName) ;
		this.AgregateIds[ this.CurrentAgregName ] = this.AgregateNum;
		
		// lit all the other tags that have at least 1 word in common with the current tag
		this.LitTagsWithAtLeastOneKwInCommon(this.CurrentAgregName) ;
		
		// formating agregate
		var Agregate = document.createElement('li');
		Element.extend(Agregate);
		Agregate.id = 'agreg_' + this.AgregateNum;
		var s_Code = '<a href="#" onclick="AgregatorObj.Delete(\''+this.CurrentAgregName+'\', true); return false" style="margin-right: 20px;">' ;
		s_Code += '<img src="./img/common/icons/bin.gif" width="11" height="13" border="0" /></a> ' ;
		s_Code += '<b><a href="#" onclick="AgregatorObj.SelectAgregate(\''+this.CurrentAgregName+'\'); return false;">' + this.CurrentAgregName + '</a></b>' ;
		s_Code += '<a href="#" onclick="AgregatorObj.CloseAgregate(\''+this.CurrentAgregName+'\'); return false;" title="Fermet l\'agr&eacute;gat" class="CloseAgregate">' ;
		s_Code += '<img src="img/common/icons/confirm.gif" width="14" height="14" border="0" /></a>' ;
		s_Code += ' : ' ;
		s_Code += this.CurrentAgregName ;
		s_Code += '<a href="#" onclick="AgregatorObj.DeleteAgregateItem(\''+this.CurrentAgregName+'\', \''+this.CurrentAgregName+'\'); return false;">' ;
		s_Code += '<img src="./img/common/icons/delete_gray.gif" width="14" height="14" border="0" /></a>'
		Agregate.innerHTML = s_Code ;
		Agregate.addClassName('selected') ;
		$('agreg_content').appendChild(Agregate);
		
		// lit off the previous tag
		if(TagHandleObj.CurTagIdAux != '')
			$(TagHandleObj.CurTagIdAux).style.color = '444' ;
		
		// lit on the new tag for agregation
		var Tags = $$('#MainTC a') ;
		// alert(Tags.inspect());
		for(i = 0 ; i < Tags.length ; i++)
		{
			if(Tags[i].innerHTML == CurTag.innerHTML)
			{
				// alert(Tags[i].id);
				Tags[i].addClassName('TagLit') ;
				Tags[i].addClassName('TagSelected') ;
			}
		}
		
		// hide the icon set
		$(TagHandleObj.RollOverIconSet).hide();
		
		TagHandleObj.CurTagIdAux = TagHandleObj.CurTagId ;
		$('agreg_form').show();
		
		this.AgregateNum++ ;
	}
	,
	SelectAgregate : function(AgregName)
	{
		// if another agreg was previously lit, lit off pliz
		this.CloseAgregate() ;
		
		// set current agreg name
		this.CurrentAgregName = AgregName ;
		
		// lit on the agreg
		var Agregate = $('agreg_' + this.AgregateIds[AgregName]);
		Agregate.addClassName('selected') ;
		// show the 'close agregate' icon in the agregate
		aCloseAgreg = Agregate.getElementsByClassName('CloseAgregate') ;
		aCloseAgreg[0].show() ;
		
		// lit all the other tags that have at least 1 word in common with the current tag
		this.LitTagsWithAtLeastOneKwInCommon(this.CurrentAgregName) ;
		
		// lit on the tag in the tag cloud
		var Tags = $$('#MainTC a') ;
		for(i = 0 ; i < Tags.length ; i++)
		{
			if(Tags[i].innerHTML == AgregName)
				Tags[i].addClassName('TagSelected') ;
		}
	}
	,
	DeleteAgregateItem : function(AgregName, AgregItemName)
	{
		// if there is only one => delete the agregate
		if(this.Agregates[ AgregName ].length == 1)
		{
			this.Delete(AgregName, false) ;
			return ;
		}
		
		// if the agreg item is the agreg name => make new agreg
		if(AgregItemName == AgregName)
		{
			for(var i = 0 ; i < this.Agregates[ AgregName ].length ; i++)
			{
				if(this.Agregates[ AgregName ][i] == AgregItemName)
					break ;
			}
			var NewAgregName = this.Agregates[ AgregName ][i+1] ;
			
			var iPos = this.AgregateNames.indexOf(AgregName) ;
			if(iPos > -1)	this.AgregateNames[iPos] = NewAgregName ;
			else			this.AgregateNames.push(NewAgregName) ;
			
			this.Agregates[ NewAgregName ] = this.Agregates[ AgregName ].without(AgregItemName) ;
			this.AgregateIds[ NewAgregName ] = this.AgregateIds[ AgregName ] ;
			this.CurrentAgregName = NewAgregName ;
			
			delete this.Agregates[ AgregName ] ;
			delete this.AgregateIds[ AgregName ] ;
			this.ReGenerateAgreg(NewAgregName) ;
		}
		else
		{
			// just delete the agreg item & regenerate both agreg & TC
			this.Agregates[ AgregName ] = this.Agregates[ AgregName ].without(AgregItemName) ;
			this.ReGenerateAgreg(AgregName) ;
		}
		
		UpdateMainTC() ;
	}
	,
	ReGenerateAgreg : function(ps_AgregName)
	{
		// get it
		Agreg = $("agreg_" + this.AgregateIds[ ps_AgregName ]) ;
		// empty it (optional)
		// Agreg.innerHTML = '' ;
		// fill it
		var s_Code = '<a href="#" onclick="AgregatorObj.Delete(\''+ps_AgregName+'\', true); return false" style="margin-right: 20px;">' ;
		s_Code += '<img src="./img/common/icons/bin.gif" width="11" height="13" border="0" /></a> ' ;
		s_Code += '<b><a href="#" onclick="AgregatorObj.SelectAgregate(\''+ps_AgregName+'\'); return false;">' + ps_AgregName + '</a></b>' ;
		s_Code += '<a href="#" onclick="AgregatorObj.CloseAgregate(\''+this.CurrentAgregName+'\'); return false;" title="Fermet l\'agr&eacute;gat" class="CloseAgregate">' ;
		s_Code += '<img src="img/common/icons/confirm.gif" width="14" height="14" border="0" /></a>' ;
		s_Code += ' : ' ;
		
		this.Agregates[ ps_AgregName ].each(function(item)
		{
			s_Code += item ;
			s_Code += '<a href="#" onclick="AgregatorObj.DeleteAgregateItem(\''+ps_AgregName+'\', \''+item+'\'); return false;">' ;
			s_Code += '<img src="./img/common/icons/delete_gray.gif" width="14" height="14" border="0" /></a>, ' ;
		});
		Agreg.innerHTML = s_Code.substr(0, s_Code.length - 2) ;
		
		// the 'close agregate' icon is lit by default, hide it if the agreg is not currently selected
		aCloseAgreg = Agreg.getElementsByClassName('CloseAgregate') ;
		if(ps_AgregName != this.CurrentAgregName)
			aCloseAgreg[0].hide() ;
	}
	,
	MergeAgregates : function(AgregateNameInto, AgregateNameToMerge)
	{
		alert('merging ' + AgregateNameToMerge + ' in ' + AgregateNameInto);
		
		for(var i = 0 ; i < this.Agregates[AgregateNameToMerge].length ; i++)
		{
			this.Agregates[AgregateNameInto].push( this.Agregates[AgregateNameToMerge][i] ) ;
		}
		
		this.ReGenerateAgreg(AgregateNameInto) ;
		this.Delete(AgregateNameToMerge, true) ;
	}
	,
	AddAgregateItem : function()
	{
		var CurTag = $(TagHandleObj.CurTagId) ;
		
		if(this.AgregateNames.indexOf(CurTag.innerHTML) > -1)
		{
			this.MergeAgregates(this.CurrentAgregName, CurTag.innerHTML) ;
			return ;
		}
		
		// do not add the same item twice
		for(i = 0 ; i < this.Agregates[ this.CurrentAgregName ].length ; i++)
		{
			if(this.Agregates[ this.CurrentAgregName ][i] == CurTag.innerHTML)
				return ;
		}
		
		// add the item
		this.Agregates[ this.CurrentAgregName ].push(CurTag.innerHTML) ;
		var s_Code = ', ' + CurTag.innerHTML ;
		s_Code += '<a href="#" onclick="AgregatorObj.DeleteAgregateItem(\''+this.CurrentAgregName+'\', \''+CurTag.innerHTML+'\'); return false;">' ;
		s_Code += '<img src="./img/common/icons/delete_gray.gif" width="14" height="14" border="0" /></a>'
		$('agreg_' + this.AgregateIds[ this.CurrentAgregName ]).innerHTML += s_Code ;
		
		// $('IcoSet2').hide();
		
		UpdateMainTC() ;
	}
	,
	GetSerializedData : function()
	{
		var Data = '' ;
		for(j = 0 ; j < this.AgregateNames.length ; j++)
		{
			if(this.AgregateNames[j] == null)
				continue;
				
			if(this.Agregates[ this.AgregateNames[j] ] == null)
				continue ;
				
			for(i = 0 ; i < this.Agregates[ this.AgregateNames[j] ].length ; i++)
				Data += this.Agregates[ this.AgregateNames[j] ][i] + ',' ;
		
			Data = Data.substr(0, Data.length - 1) + ':' ;
		}
		
		return Data.substr(0, Data.length - 1) ;
	}
	,
	CloseAgregate : function(AgregName)
	{
		if((!AgregName) || (AgregName == 'undefined'))
		{
			if(this.CurrentAgregName == '')
				return ;
		}
		else
		{
			this.CurrentAgregName = AgregName ;
		}
		
		var Tags = $$('#MainTC a') ;
	
		for(i = 0 ; i < Tags.length ; i++)
		{
			if(Tags[i].innerHTML == this.CurrentAgregName)
			{
				Tags[i].removeClassName('TagSelected') ;
				
			}
			
			if(Tags[i].hasClassName('TagWithWordInCommon'))
				Tags[i].removeClassName('TagWithWordInCommon') ;
		}
		
		// remove the selected style
		$('agreg_' + this.AgregateIds[ this.CurrentAgregName ]).removeClassName('selected');
		// hide the 'close agregate' icon in the agregate
		aCloseAgregate = $('agreg_' + this.AgregateIds[ this.CurrentAgregName ]).getElementsByClassName('CloseAgregate');
		aCloseAgregate[0].hide() ;
		
		this.CurrentAgregName = '' ;
		
		// $('IcoSet3').hide();
	}
	,
	Delete : function(ps_AgregateName, pb_UpdateTC)
	{
		if((!ps_AgregateName) || (ps_AgregateName == 'undefined'))
			ps_AgregateName = $(TagHandleObj.CurTagId).innerHTML ;

		if((!pb_UpdateTC) || (pb_UpdateTC == 'undefined'))
			pb_UpdateTC = true ;
	
		// remove the agregation line
		// alert('ps_AgregateName = ' + ps_AgregateName + ', pb_UpdateTC='+pb_UpdateTC );
		$('agreg_content').removeChild($('agreg_' + this.AgregateIds[ ps_AgregateName ]));
		
		var iPos = this.AgregateNames.indexOf(ps_AgregateName) ;
		if(iPos > -1)	delete this.AgregateNames[iPos] ;
		delete this.Agregates[ ps_AgregateName ] ;
		delete this.AgregateIds[ ps_AgregateName ] ;
		
		if(ps_AgregateName == this.CurrentAgregName)
			this.CurrentAgregName = '' ;
		
		// if no line left => hide agregator
		if($('agreg_content').childElements().length == 0)
			$('agreg_form').hide();
			
		// update TC
		if(pb_UpdateTC)
			UpdateMainTC() ;
		else
		{
			// removed tag selected & lit styles
			// var Tags = $('MainTC').childElements() ;
			var Tags = $('MainTC').getElementsByTagName('a') ;
	
			for(i = 0 ; i < Tags.length ; i++)
			{
				if(Tags[i].innerHTML == ps_AgregateName)
				{
					Tags[i].removeClassName('TagSelected') ;
					Tags[i].removeClassName('TagLit') ;
					// break ;
				}
			}
		}
	}
}