
// Définition de la classe 'CarSelectorChart'
// NB: L'ordre des méthodes est important

CarSelectorChart.Instances = new Array();

function CarSelectorChart(id)
{
	// Outil pour récupérer une instance par son identifiant
	CarSelectorChart.Instances[id] = this;

	// Champs privés
	var _contentWidth = 0;
	var _currentSelectedItem = null;
	var _currentTabProperty = null;
	var _currentTabValues = null;
	var _position = null;
	var _scales = document.getElementById(id + "ChartScales");
	var _content = document.getElementById(id + "ChartContent");
	var _items = null;

	// Propriétés publiques
	this.HtmlObject = document.getElementById(id);
	this.OnItemClick = new Array();
	this.OnItemOver = new Array();
	this.OnItemOut = new Array();

	// Méthodes privées

	var SelectFirst = function(results, model, bodyGroup, priceProperty)
	{
		var count = results.length;
		var item = null;
		for (var i = 0; i < count; i++)
		{
			var result = results[i];
			if ((result.Model == model && result.GrBodyStyle == bodyGroup)
				&& (item == null || result[priceProperty] < item[priceProperty]))
					item = result;
		}
		return item;
	}

	// L'échelle est peut-être logarithmique, c'est pourquoi on ne peut pas déduire
	// la position par une simple règle de trois. On doit retrouver les paliers concernés
	// par la valeur puis interpoler dans ce palier pour trouver la bonne position.
	var GetLeft = function(value)
	{
		for (var i = 0; i < _currentTabValues.length - 1; i++)
			if (_currentTabValues[i + 1].Value > value)
			{
				var scaleMin = _currentTabValues[i];
				var scaleMax = _currentTabValues[i + 1];
				var ratio = (scaleMax.Left - scaleMin.Left) / (scaleMax.Value - scaleMin.Value);
				return scaleMin.Left + ratio * (value - scaleMin.Value);
			}
		return 0;
	}

	// Méthode publiques

	// Retrouve le HTML associé à chaque couple
	// pour pouvoir les manipuler plus tard
	this.FindItems = function (items)
	{
		_items = new Object();
		var thisp = this;
		for (var i = 0; i < items.length; i++)
		{
			var item = items[i];
			var itemId = "Item__{0}__{1}".format(item.Model, item.GrBodyStyle);
			var obj = new CarSelectorItem(itemId);
			
			obj.OnClick.push(function (sender, args)
			{
				// (Dé)sélectionne le couple (avec la case cochée et un bleu plus foncé)
				if (sender.HtmlObject.className.indexOf("Selected") < 0)
				{
					if (_currentSelectedItem != null)
						_currentSelectedItem.HtmlObject.className = "CarSelectorItem";
					sender.HtmlObject.className = "CarSelectorItem Selected";
					_currentSelectedItem = sender;
				}
				else
				{
					sender.HtmlObject.className = "CarSelectorItem";
					_currentSelectedItem = null;
				}
				Tools_DispatchEvent(thisp.OnItemClick, thisp, args);
			});
			
			if (_position == null)
				_position = Tools_GetPosition(this.HtmlObject);
			
			obj.OnOver.push(function (sender, args)
			{
				args.Top = sender.HtmlObject.offsetTop + (_content.offsetTop - _content.scrollTop);
				args.Left = sender.GetImagesLeft() + _position.Left;
				args.Height = sender.HtmlObject.offsetHeight;
				Tools_DispatchEvent(thisp.OnItemOver, thisp, args);
			});
			
			obj.OnOut.push(function (sender, args)
			{
				Tools_DispatchEvent(thisp.OnItemOut, thisp, args);
			});
			
			_items[itemId] = obj;
		}
	}

	this.AnimateItemArrows = function(start, end, itemId)
	{
		var widthGap = end.Width - start.Width;
		var leftGap = end.Left - start.Left;
		var timer = 0;
		for (var i = 0; i <= 100; i += 10)
		{
			var t = Tools_Smooth(i * 0.01);
			var left = start.Left + leftGap * t;
			var width = start.Width + widthGap * t;
			setTimeout("CarSelectorItem.Instances['{0}'].SetArrowSize({1}, {2})".format(itemId, left, width), 40 * timer);
			timer++;
		}
	}

	this.AnimateItemImages = function(start, end, itemId)
	{
		var gap = end - start;
		var timer = 0;
		for (var i = 0; i <= 100; i += 10)
		{
			var left = start + gap * Tools_Smooth(i * 0.01);
			setTimeout("CarSelectorItem.Instances['{0}'].SetImagesLeft({1})".format(itemId, left), 40 * timer);
			timer++;
		}
	}
	
	// Renvoie le nombre d'items dans le graphique
	this.GetItemCount = function ()
	{
		var count = 0;
		for (var key in _items)
		{
			var item = _items[key];
			if (item.IsVisible && item.IsVisible())
				count++;
		}
		return count;
	}

	// Met à jour la partie graphique centrale
	// en fonction des résultats de la requête
	this.UpdateItems = function (results, animate, priceProperty)
	{
		var topStack = 0;
		var moved = new Array();
		for (var key in _items)
		{
			var item = _items[key];
			if (!item.Hide)
				continue ;

			var result = SelectFirst(results, item.Model, item.GrBodyStyle, "Min" + priceProperty);
			if (result != null)
			{
				// On met à jour les informations des couples
				item.SetPriceLabel(result.PriceLabel);

				var min = result["Min" + _currentTabProperty];
				var max = result["Max" + _currentTabProperty];
				if (!min || !max)
					continue ;

				var firstTime = item.NeverShown;
				// Le couple a été trouvé dans les résultats: on doit l'afficher
				if (item.HtmlObject.style.display == "none")
					item.Show();

				var imagesSize = item.GetImagesSize();	
				item.HtmlObject.style.top = topStack + "px";
				topStack += Math.max(imagesSize.Height, 30);

				// On calcule la position puis la largeur de la flèche
				var arrowLeft = GetLeft(min);
				var arrowWidth = Tools_Max(GetLeft(max) - arrowLeft, 30);

				// Ajuste la position du véhicule et du label
				var imagesWidth = imagesSize.ThumbWidth + imagesSize.LabelWidth;			// Calcule la largeur des 2 images (vignette + label)
				var imagesLeft = arrowLeft - 10 - imagesWidth;								// En pire cas on place les images avant la flèche

				// On peut placer les images à l'intérieur de la flèche à condition que le libellé ne dépasse pas à droite
				
			
		//GLN: Mise en commentaire de l'ancien code, ajout d'un code pour mettre l'image de la voiture juste après la checkbox et sur la flèche si l'espace le permet
				//if ((arrowLeft + 20 + imagesSize.ThumbWidth + 5 < arrowLeft + arrowWidth)
				//	&& (arrowLeft + 20 + imagesWidth < _content.offsetWidth))			
				//	imagesLeft = arrowLeft + 20;											// --> Une marge de 20px à gauche
				//else if (arrowLeft + arrowWidth + 25 + imagesWidth < _content.offsetWidth)	// On peut placer les images à droite de la flèche
				//	imagesLeft = arrowLeft + arrowWidth + 5;								// --> Une marge de 20px à droite
				if (arrowLeft + 20 + imagesWidth < _content.offsetWidth)
					imagesLeft = arrowLeft + 20;
		//GLN: Fin Mise en commentaire
		
				// Si la vignette n'est pas visible on ne l'anime pas
				var itemMinY = item.HtmlObject.offsetTop;
				var itemMaxY = item.HtmlObject.offsetTop + imagesSize.Height;
				var contentMinY = _content.scrollTop;
				var contentMaxY = _content.offsetHeight + _content.scrollTop;
				var notVisible = (itemMinY < contentMinY && itemMaxY < contentMinY)
					|| (itemMinY > contentMaxY && itemMaxY > contentMaxY);

				if (firstTime || notVisible || animate == false)		// On n'anime pas les vignettes
				{
					item.SetArrowSize(arrowLeft, arrowWidth);
					item.SetImagesLeft(imagesLeft);
				}
				else													// On anime les vignettes
				{
					this.AnimateItemArrows(item.GetArrowSize(), { Left: arrowLeft, Width: arrowWidth }, item.Id);
					this.AnimateItemImages(item.GetImagesLeft(), imagesLeft, item.Id);
				}
				
				moved.push(item);
				
				// S'il n'y a qu'un seul élément dans les résultats on simule un clic dessus
				if ((results.length == 1) && (item.HtmlObject.className.indexOf("Selected") < 0))
					item.OnItemClick(null);
			}
			else
			{
				// Le couple n'a pas été trouvé dans les résultats ou il
				// ne possède pas les valeurs requises --> on le masque
				if (item.HtmlObject.style.display == "block")
				{
					if (item.HtmlObject.className.indexOf("Selected") != -1)
						item.OnItemClick(null);
					item.Hide();
				}
			}
		}

		// On ajuste l'espace entre les véhicules si on le peut
		if (topStack < _content.offsetHeight)
		{
			var space = _content.offsetHeight / (moved.length + 1);
			var topStack = space;
			Tools_ForEach(moved, function(item)
			{
				item.HtmlObject.style.top = (topStack - item.GetImagesSize().Height / 2) + "px";
				topStack += space;
			});
		}
	}

	this.SetSize = function (width, height)
	{
		this.HtmlObject.style.width = width + "px";
		this.HtmlObject.style.height = height + "px";

		_content.style.height = height + "px";
		_content.style.width = width + "px";

		_scales.style.width = width + "px";
		_scales.style.height = height + "px";
	}

	this.SetScale = function (property)
	{
		if (_currentTabProperty != null)
			Tools_Show(_currentTabProperty + "ChartScale", false);
		_currentTabProperty = property;

		// On affiche l'échelle et on ré-ajuste la hauteur de la partie centrale
		// (pour éviter d'éventuels problèmes avec une description trop longue)
		var contentHeight = this.HtmlObject.offsetHeight;
		
		Tools_Show(_currentTabProperty + "ChartScale", true);
		var rule = document.getElementById(_currentTabProperty + "ChartRule");
	
		// On ajuste les colonnes du fond
		var scaleColumns = document.getElementById(property + "ChartColumns");
		if (scaleColumns != null)
			scaleColumns.style.height = (contentHeight + rule.offsetHeight) + "px";
	
		// On retrouve les valeurs de l'échelle en cours
		var scaleValues = document.getElementById(property + "ChartRuleValues");
		if (scaleValues != null)
		{
			// On récupère la taille de la marge (la dernière cellule) à droite
			var scaleLines = document.getElementById(property + "ChartRuleLines");
			var cells = scaleLines.getElementsByTagName("td");
			var lastCellWidth = cells[cells.length - 1].offsetWidth;

			_currentTabValues = new Array();
			_contentWidth = (_content.offsetWidth - lastCellWidth);

			var spans = scaleValues.getElementsByTagName("span");
			var stepWidth = _contentWidth / (spans.length - 1);
			for (var i = 0; i < spans.length; i++)
				_currentTabValues.push({ Left: (i * stepWidth), Value: parseInt(spans[i].innerHTML) });
		}
	}

	this.GetSelectedItem = function()
	{
		return _currentSelectedItem;
	}
}

