
// Nécessaires pour le layer 360...
var swfData, swfTrimData;

// Définition de la classe principale 'CarSelector'
// NB: L'ordre des méthodes est important

// Cette classe est un singleton
CarSelector.GetInstance = function()
{
	if (Tools_IsNullOrEmpty(CarSelector.Instance))
		CarSelector.Instance = new CarSelector();	
	return CarSelector.Instance;
}

function CarSelector()
{
	// Cette classe est un singleton
	if (CarSelector.Instance)
		return CarSelector.Instance;

	// Champs privés
	var _tabs = new CarSelectorTabs("tabs");
	var _choices = new CarSelectorChoices("choices");
	var _chart = new CarSelectorChart("chart");
	var _choicesTooltip = new CarSelectorTooltip("choicesTooltip");
	var _chartTooltip = new CarSelectorTooltip("chartTooltip");
	var _infoPanel = new CarSelectorInfoPanel("infoPanel", infos);
	var _chartTooltipDelay = 500;
	var _startHeight = 0;
	
	var _budgetApproach = new BudgetApproach("budgetApproach");
	
	// Variable permettant de tester si l'utilisateur a annulé ses choix
	
	var _topPart = document.getElementById("topPart");
	var _layoutTable = document.getElementById("layoutTable");
	
	var _configButtonLink = document.getElementById("configureButton");
	var _discoverButtonLink = document.getElementById("discoverButton");
	var _testButtonLink = document.getElementById("testButton");
	var _testButton = document.getElementById("testButton");
	
	var _buttons = $(".RightPartButtons")[0];
	var _layer360 = document.getElementById("layer360");
	var _overChoiceId = null;

	// Méthodes privées

	var OnTabsChanged = function(sender, property)
	{
		// Taggage WeboScope des onglets
		if (weboScripts)
			switch (property)
			{
				case "Performance": eval(weboScripts.Perfs.format("")); break ;
				case "CO2Rate": eval(weboScripts.Co2.format("")); break ;
				case "MixedConsumption": eval(weboScripts.Conso.format("")); break ;
				default: if (Tools_EndsWith(property, "Price")) eval(weboScripts.Price.format("")); break ;
			}
	
		_chart.SetScale(property);
		OnChanged(property);
	}
	
	var PropertyFilter = function(item, selection, tabProperty)
	{
		return Tools_IsSubsetOf(selection, item)
			&& Tools_IsNullOrEmpty(item["Min" + tabProperty]) == false
			&& Tools_IsNullOrEmpty(item["Max" + tabProperty]) == false;
	}

	// Filtre de l'approche budgétaire
	var BudgetApproachFilter = function(item)
	{
		if (_budgetApproach.IsSet == false)
			return true;
	
		// S'il n'y pas d'intersection des intervalles de prix alors vous êtes le maillon faible
		var priceProperty = _tabs.GetProperty(0);
		var itemMinPrice = item["Min" + priceProperty];
		var itemMaxPrice = item["Max" + priceProperty];
		
		if ( /* (itemMinPrice < _budgetApproach.MinPrice && itemMaxPrice < _budgetApproach.MinPrice) || */
			(itemMinPrice > _budgetApproach.MaxPrice && itemMaxPrice > _budgetApproach.MaxPrice))
			return false;
			
		// On limite les prix à l'intervalle budgétaire
		/*
		if (itemMinPrice < _budgetApproach.MinPrice)
		{
			item["Min" + priceProperty] = _budgetApproach.MinPrice;
			item["PriceLabel"] = _budgetApproach.MinPriceLabel;
		}
		*/
		if (itemMaxPrice > _budgetApproach.MaxPrice)
			item["Max" + priceProperty] = _budgetApproach.MaxPrice;
			
		return true;
	}

	var ReduceMethod = function(a, b, tabProperty, priceProperty)
	{
		// On ne garde que le prix minimum
		if (a["Min" + priceProperty] > b["Min" + priceProperty])
		{
			a["Min" + priceProperty] = b["Min" + priceProperty];
			a.PriceLabel = b.PriceLabel;
		}		
		a["Min" + tabProperty] = Tools_Min(a["Min" + tabProperty], b["Min" + tabProperty]);
		a["Max" + tabProperty] = Tools_Max(a["Max" + tabProperty], b["Max" + tabProperty]);
		return a;
	}

	var MapMethod = function(item, tabProperty, priceProperty)
	{
		var obj = { Model: item.Model, GrBodyStyle: item.GrBodyStyle, PriceLabel: item.PriceLabel };
		obj["Min" + tabProperty] = item["Min" + tabProperty];
		obj["Max" + tabProperty] = item["Max" + tabProperty];
		if (tabProperty != priceProperty)
		{
			obj["Min" + priceProperty] = item["Min" + priceProperty];
			obj["Max" + priceProperty] = item["Max" + priceProperty];
		}
		return obj;
	}

	// La sélection des critères à gauche ou l'onglet a changé.
	// L'onglet et les nouveaux choix sont spécifiés en paramètre.
	var OnChanged = function(tabProperty, selection)
	{
		// On récupère la propriété de l'onglet en cours
		if (Tools_IsNullOrEmpty(tabProperty))
			tabProperty = _tabs.GetSelection();

		// On récupère la sélection des critères
		if (Tools_IsNullOrEmpty(selection))
			selection = _choices.GetSelection();
		if (selection == null || tabProperty == null)
			return false;

		// Définition des méthodes de projection et d'aggrégation
		var priceProperty = _tabs.GetProperty(0);
		var mapMethod = function (item) { return MapMethod(item, tabProperty, priceProperty); }
		var reduceMethod = function (a, b) { return ReduceMethod(a, b, tabProperty, priceProperty); }

		// A: vérifie si l'élément matche les critères de choix et possède les propriétés requises
		// B: ne garde que les propriétés requises par les onglets pour placer les vignettes
		// C: vérifie les contraintes budgétaires si le financement est en place
		// D: regroupe les éléments par modèle et regroupement de silhouettes
		var groups = items
			.filter(function(item) { return PropertyFilter(item, selection, tabProperty) })	// A
			.map(mapMethod)																	// B
			.filter(BudgetApproachFilter)													// C
			.groupBy(function(item) { return item.Model + "_" + item.GrBodyStyle; });		// D

		// On réduit les groupes pour n'obtenir qu'un seul modèle
		// avec le min et le max pour la caractéristique en cours
		for (var i = 0; i < groups.length; i++)
			groups[i] = groups[i].reduce(reduceMethod);

		// On affiche les résultats
		_chart.UpdateItems(groups, true, priceProperty);

		return (groups.length > 0);
	}

	// L'utilisateur a effectué un choix. Si l'élément sur lequel
	// il a cliqué était désactivé, on doit ajuster ces précédents choix
	// en supprimant successivement le plus vieux choix tant qu'il n'y a
	// pas de résultats (au moins 1 modèle doit apparaitre au final)
	var OnChoicesChanged = function(sender, args)
	{
		// Taggage WeboScope des critères
		if (weboScripts)
		{
			var choice = _choices.GetSelectedItem(args.GroupCode);
			if (choice != null)
			{
				var label = Tools_Trim(choice.textContent ? choice.textContent : choice.innerText).replace("'", "\\'");
				switch (args.GroupCode)
				{
					case "VersionCriterion": eval(weboScripts.Marketing.format(label)); break ;
					case "GrBodyStyle": eval(weboScripts.Body.format(label)); break ;
					case "GrTransmissionType": eval(weboScripts.Trans.format(label)); break ;
					case "Energy": eval(weboScripts.Energy.format(label)); break ;
				}
			}
		}

		var selection = _choices.GetSelection();
		var tabProperty = _tabs.GetSelection();
		var selectedItem = _chart.GetSelectedItem();

		if (selectedItem != null)
		{
			var applicationPath = window.location.href.substr(0, window.location.href.indexOf('/Pages'));
			UpdateConfigButton(applicationPath, selectedItem.Model, selectedItem.GrBodyStyle);
		}

		// SFG: On doit assurer la cohérence des énergies
		if (args.GroupCode == "Energy" && Tools_IsNullOrEmpty(_budgetApproach.Energy) == false)
		{
			var choice = _choices.GetSelectedItem(args.GroupCode);
			var energyLabel = Tools_Trim($(choice).text());
			if (energyLabel != _budgetApproach.Energy)
			{		
				_budgetApproach.Reset();
				_choices.UpdateGroupStyles(null, false);
			}
		}

		// On enlève le choix le plus ancien tant qu'il n'y a pas de résultats
		if (OnChanged(tabProperty, selection) == false)
		{
			var oldestChoice = _choices.HistoryGetOldest();
			if (Tools_IsNullOrEmpty(oldestChoice) == false)
			{
				var item = _choices.GetSelectedItem(oldestChoice);
				_choices.OnClick(item, true);
				return ;
			}
		}

		// On met à jour le prix à droite
		var selectedItem = _chart.GetSelectedItem();
		if (selectedItem != null)
			_infoPanel.UpdatePriceLabel(selectedItem.PriceLabel);

		// On met à jour le style des choix et on s'occupe des inductions
		var selection = _choices.GetSelection();
		_choices.UpdateSelection(selection, args.GroupCode, args.Induced, items);
	}

	// On ajuste la hauteur des choix à la hauteur de la fenêtre
	var SetChoicesHeight = function()
	{
		var choicesPanelBottom = document.getElementById("choicesPanelBottom");
		if (choicesPanelBottom != null)
			_choices.HtmlObject.style.height = (_startHeight - choicesPanelBottom.offsetHeight) + "px";
	}

	var SelectCurrent360 = function()
	{
		var inputs = _layer360.getElementsByTagName("input");
		for (var i = 0; i < inputs.length; i++)
		{
			var input = inputs[i];
			if (input.parentNode.className == "bordurePicto")
			{
				Tools_FireClickEvent(input);
				break ;
			}
		}
	}

	var OnExteriorClick_Response = function(response)
	{
		_layer360.innerHTML = response.html;
		eval(response.colors.replace("var swfData=", "swfData="));
		eval(response.trims.replace("var swfTrimData=", "swfTrimData="));

		Layer360_OnLoad();

		var closeButton = document.getElementById("lnkCloseLayer");
		closeButton.href = "#";

		_layer360.style.display = "block";
		setTimeout(SelectCurrent360, 500);

		Tools_Show("TabTrimsSWF", false);
		Tools_Show("gli_mask", true);
		Tools_Show("LayerChoiceColor", true);
	}

	var OnExteriorClick = function(sender, args)
	{
		var params = { model: args.Model, bodyGroup: args.GrBodyStyle };
		Ajax_Execute(location.pathname, "GetExteriorHtml", params, OnExteriorClick_Response);
	}

	var OnChartItemOver = function(sender, args)
	{
		_choicesTooltip.Hide();
		var targetX = args.MouseLeft + 20, targetY = args.MouseTop;
		var pos = _chartTooltip.GetPosition();
		if ((_chartTooltip.IsVisible() == false) || (pos.X != targetX || pos.Y != targetY))
		{
			var currentItemCode = args.Model + "_" + args.GrBodyStyle;
			if (_chartTooltip.CurrentItemCode != currentItemCode)
			{
				_chartTooltip.CurrentItemCode = currentItemCode;
				var infos = _infoPanel.GetInfos(args.Model, args.GrBodyStyle);
				if (Tools_EndsWith(infos.BigImage, ".swf"))
					_chartTooltip.SetText('<embed width="200px" height="110px" quality="high" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" type="application/x-shockwave-flash" src="' + infos.BigImage + '"/>');
				else
				{
					var guid = Tools_CreateGuid();
					_chartTooltip.SetText("<img id='{0}' src='{1}' width='200px' height='120px' />".format(guid, infos.BigImage));
					if (document.body.className == "IE6")
					{
						var img = document.getElementById(guid);
						if (img != null)
							doFix(img);
					}
				}

				if (_chartTooltip.IsVisible() == false)
					setTimeout(function()
					{
						if (_chartTooltip.CurrentItemCode == currentItemCode)
						{
							if (document.body.className != "IE6")
								Tools_SetAlpha(_chartTooltip.HtmlObject.id, 0);
							_chartTooltip.Show();
							if (document.body.className != "IE6")
								Tools_Fade(_chartTooltip.HtmlObject.id, 0, 100);
						}
					}, _chartTooltipDelay);
			}
			_chartTooltip.SetPosition(targetX, targetY, args.Height);
		}
	}

	var OnChartItemClick = function(sender, args)
	{
		if (sender.GetSelectedItem() != null)
			UpdatePanel(args.Model, args.GrBodyStyle, args.PriceLabel);
		else
			ResetPanel();
	}

	var OnChartItemOut = function(sender, args)
	{
		_chartTooltip.CurrentItemCode = null;
		_chartTooltip.Hide();
	}

	var ResetPanel = function()
	{
		_buttons.style.display = "none";
		_infoPanel.Reset();
	}

	var UpdateConfigButton = function(applicationPath, model, bodyGroup)
	{
		var params = Tools_GetQueryParams();
		var language = Tools_Default(params["language"], params["Language"]);
		var languageAO = Tools_Default(params["languageAO"], params["LanguageAO"]);
		var url = "{0}/Pages/Configurator/chooseGrade.aspx?Language={1}&LanguageAO={2}&Model={3}&GrBodyStyle={4}"
			.format(applicationPath, language, languageAO, model, bodyGroup);
			
		if (_budgetApproach.IsSet)
			url += "&FinancingBudget={0}&FinancingMin={1}&FinancingMax={2}&FinancingSessionId={3}"
				.format(_budgetApproach.MonthlyBudget, _budgetApproach.MinPrice,
				_budgetApproach.MaxPrice, _budgetApproach.SessionId);
		
		var filter = '';
		var selection = _choices.GetSelection();
		for (var key in selection)
		{
			var s = '' + selection[key];
			if (s.indexOf('function') < 0 && (key != 'GrBodyStyle'))
				filter += '&' + key + '=' + s;
		}

		url += filter;
		
		var infos = _infoPanel.GetInfos(model, bodyGroup);
		if (infos.ConfigureUrl)
		{
			var parsedUrl = Tools_ParseUrl(url);
			url = Tools_GetUrl(infos.ConfigureUrl, parsedUrl.Params);
			_configButtonLink.href = "javascript:OpenLink('" + url + "', 'Standard');";
		}
		else _configButtonLink.href = url;
		
		return infos;
	}

	var UpdatePanel = function(model, bodyGroup, priceLabel)
	{
		// On met à jour les boutons en bas à droite
		var applicationPath = window.location.href.substr(0, window.location.href.indexOf('/Pages'));
		var infos = UpdateConfigButton(applicationPath, model, bodyGroup);
		
		if (infos.IsShowRoomVisible)
			document.getElementById("discoverButton").style.display = "block";
		else
			document.getElementById("discoverButton").style.display = "none";
		
		if (infos.DiscoverUrl)
			_discoverButtonLink.href = "javascript:OpenLink('" + infos.DiscoverUrl + "', 'Standard');";
		else
		{
			var params = Tools_GetQueryParams();
			var language = Tools_Default(params["language"], params["Language"]);
			var languageAO = Tools_Default(params["languageAO"], params["LanguageAO"]);
			_discoverButtonLink.href = "{0}/Pages/Range/model.aspx?Language={1}&LanguageAO={1}&Model={2}&GrBodyStyle={3}"
				.format(language, languageAO, applicationPath, model, bodyGroup);
		}	

		if (infos.TestDriveUrl)
		{
			_testButtonLink.href = '#';
			
			//GLN Ajout-Modification
			_testButtonLink.onclick = function()
			{
				eval(infos.TestDriveUrl);
				if (weboScripts)
					eval(weboScripts.Test.format("TestDrive"));
				return true;
			}
			_testButton.style.display = "block";
			
		}
		else _testButton.style.display = "none";

		// Taggage weboScope
		if (weboScripts)
		{
			_configButtonLink.onclick = function() { eval(weboScripts.Configure.format("Configure")); return true; }
			_discoverButtonLink.onclick = function() { eval(weboScripts.Discover.format("Discover")); return true; }
		}

		_buttons.style.display = "block";

		// On met à jour les informations à droite
		_infoPanel.Update(model, bodyGroup, _discoverButtonLink.href, priceLabel);
	}

	var OnChoiceOver = function(sender, args)
	{
		if (_choices.IsAnimating() == false	&& _overChoiceId != sender.HtmlObject.id
			&& Tools_IsNullOrEmpty(args.Description) == false)
		{
			_overChoiceId = sender.id;
			_chartTooltip.Hide();
			_choicesTooltip.SetText(args.Description);
			_choicesTooltip.Show();
			_choicesTooltip.SetPosition(0, args.Top + args.Height / 2, args.Height);
		}
	}

	var OnChoiceOut = function(sender, args)
	{
		_choicesTooltip.Hide();
	}
	
	// Un paramètre de l'approche budgétaire a change
	var OnBudgetApproachChanged = function()
	{
		// On met à jour la partie centrale
		var tabProperty = _tabs.GetSelection();
		var selection = _choices.GetSelection();
		OnChanged(tabProperty, selection);
		
		// On met à jour le prix à droite
		var selectedItem = _chart.GetSelectedItem();
		if (selectedItem != null)
			_infoPanel.UpdatePriceLabel(selectedItem.PriceLabel);
		
		if (_chart.GetItemCount() == 0)
			Tools_ShowLayerPopup('LayerBtnComparer', true);
			
		// Resize de l'accordéon
		SetChoicesHeight();
		_choices.UpdateGroupStyles(null, false);
		
		// On assure la cohérence des énergies
		if (Tools_IsNullOrEmpty(_budgetApproach.Energy) == false)
		{
			var choices = $("#choicesGroup__Energy li");
			for (var i = 0; i < choices.length; i++)
			{
				var choice = $(choices[i]);
				var choiceTitle = choice.find("div").text();
				if (Tools_Trim(choiceTitle) == _budgetApproach.Energy)
				{
					choice.click();
					break ;
				}
			}
		}
	}
	
	// Méthodes publiques
		
	this.OnResetChoices = function()
	{
		_budgetApproach.Reset();
		_choices.ResetAllSelection();
				
		OnChanged();
		
		// On déselectionne l'élément en cours
		var selectedItem = _chart.GetSelectedItem();
		if (selectedItem != null)
			selectedItem.OnItemClick(null);							

		// Resize de l'accordéon
		SetChoicesHeight();
		_choices.UpdateGroupStyles(null, false);
	}
	
	var SetSizes = function()
	{
		// Redimensionne la table principale
		var top = $(".TopTabs").height() + $(".RangeTabs").height();
		$(".LayoutTable").height($("body").height() - top);
		
		var centerSize = { Width: $(".CenterPart").width(), Height: $(".CenterPart").height() };
		
		// Redimensionne les critères de choix à gauche
		var leftButtonsHeight = $(".LeftPartButtons").height();
		$(".CarSelectorChoices").height(centerSize.Height - leftButtonsHeight - 50);
		
		// Redimensionne le graphique central
		$(".CarSelectorChart").width(centerSize.Width);
		$(".CarSelectorChart").height(centerSize.Height);
		$(".ChartScales").width(centerSize.Width);
		$(".ChartContent").width(centerSize.Width);
		$(".ChartContent").height(centerSize.Height	- $(".ChartScales").height() - 20);
		
		// Aligne les onglets du haut avec le début du graphique
		$(".TopTabs").css("margin-left", $(".LeftPart").width() + "px");
	}
	
	this.OnLoad = function()
	{
		Tools_UseExtensions();

		_choices.OnLoad();
		_choices.OnChanged.push(OnChoicesChanged);
		_choices.OnChoiceOver.push(OnChoiceOver);
		_choices.OnChoiceOut.push(OnChoiceOut);
		
		_tabs.OnChanged.push(OnTabsChanged);	

		_chart.FindItems(items);
		_chart.OnItemClick.push(OnChartItemClick);
		_chart.OnItemOver.push(OnChartItemOver);
		_chart.OnItemOut.push(OnChartItemOut);

		_infoPanel.OnExteriorClick.push(OnExteriorClick);

		// Evénements de l'approche budgétaire
		_budgetApproach.OnLoad();
		_budgetApproach.Changed.push(OnBudgetApproachChanged);

		// On ouvre le 1er onglet par défaut
		var firstProperty = _tabs.GetProperty(0);
		_chart.SetScale(firstProperty);
		_tabs.SetSelection(0, true);
		SetSizes();
		_tabs.SetSelection(0);
		
		_choicesTooltip.SetContainer(_chart.HtmlObject);
		_chartTooltip.SetContainer(_chart.HtmlObject);
		
		// ???
		var bodyClass = $(document.body).attr("class");
		if (bodyClass == "IE6" || bodyClass == "IE7" || bodyClass == "IE8") // ???
			$(".Button").click(function()
			{
				var url = $(this).attr("href");
				if (Tools_IsNullOrEmpty(url) == false)
					window.location = url;
			});
	}
}

$(window).load(function()
{
	CarSelector.GetInstance().OnLoad();
});
