﻿
/// <reference path="../../../../jQuery/1.3.2/jquery-1.3.2-vsdoc.js" />

/**
 *
 * DisplayManager
 *
 * This class manages the search configuration status within the client environment
 *
 * Managing status and communications between otherwise disparate page elements including:
 *	- Multiple, separate, flash display elements
 *	- Associated html display elements (checkbox links, html slider widgets etc) 
 *
 */

	// Check that namespace into which the Class definition will be creates has been defined & if not then create
	
	if (!mrm.global.isNamespaceDefined("mrm.common.display")) mrm.global.createNamespace("mrm.common.display", "1.0");
	
	
	// Class definition :

	mrm.common.display.DisplayManager = Object.subClass
	(
		{
			/*
			=============================
			CONSTANTS
			=============================
			*/
			SCOPE: "scope",
			SCOPE_LEVEL_1: "SCOPE_LEVEL_1",
			SCOPE_LEVEL_1_NO_PROPOGATION: "SCOPE_LEVEL_1_NO_PROPOGATION",
			SCOPE_LEVEL_2: "SCOPE_LEVEL_2",
			SCOPE_LEVEL_3: "SCOPE_LEVEL_3",
			SCOPE_ALL_LEVELS: "SCOPE_ALL_LEVELS",

			CLASS_AUTO_DISABLE_DISPLAY: "AUTO-DISABLE-DISPLAY",

			DEBUG: false,


			/*
			=============================
			CONSTRUCTOR
			=============================
			*/
			init: function ()
			{
				/*
				*********************************************
				*********************************************
				* TEMPORARY METHOD VALUE SELECTION SIMULATION
				*********************************************
				*********************************************
					 
				setTimeout(
				function ()
				{
				alert("2222222");
				var o = 
				{
				dataCategory: "DATA_CATEGORY_PRICE",
				minValue: "8000", //24915
				maxValue: "50000"//77953
				};

				mrm.runtime.display.displayManager._broadcastValueSelectionUpdate(o);
								
				},
				12000
				);
				*/
				/*
				*********************************************
				*********************************************
				*********************************************
				*********************************************
				*/



			},



			/*
			=============================
			PUBLIC MEMBERS
			=============================
			*/
			/*
			=============================
			LISTENER REGISTRATION
			=============================
			*/
			/*
			* Swf Data display host instance registration
			*/
			registerSwfDataDisplayHost: function (scope, swfHostJsClass)
			{
				if (scope == this.SCOPE_LEVEL_1)
				{
					this._swfDataDisplaysScopeLevel1.push(swfHostJsClass);
				}
				else if (scope == this.SCOPE_LEVEL_2)
				{
					this._swfDataDisplaysScopeLevel2.push(swfHostJsClass);
				}
				else throw new Error(("mrm.common.display.DisplayManager.registerSwfDataDisplayHost() :: INVALID 'scope' == " + scope));
			},



			/*
			* JS Control Class instance registration
			*/
			registerListener: function (scope, jsControlClassInstance)
			{
				if (scope == this.SCOPE_LEVEL_1)
				{
					this._listenersLevel1.push(jsControlClassInstance);
				}
				else if (scope == this.SCOPE_LEVEL_2)
				{
					this._listenersLevel2.push(jsControlClassInstance);
				}
				else if (scope == this.SCOPE_ALL_LEVELS)
				{
					this._listenersAllLevels.push(jsControlClassInstance);
				}
				else throw new Error("mrm.common.display.DisplayManager.registerListener() :: INVALID 'scope'");
			},



			/*
			* Register elements that are disabled when new data is loaded from the server via AJAX
			* 
			* The element itself is not REGISTERED
			* Instead unique jQuery 'selector' strings relating to the relevant element container nodes are stored
			*
			*
			* @param	jQuerySelectorString [String]		This is a string used in a jQuery i.e. $(disableTargetJQueryRef) will return the container element into which the disabling HTML content is added / appended
			*												THIS MUST BE A UNIQUE IDENTIFIER
			*/
			registerElementForDisableOnDataLoad: function (jQuerySelectorString)
			{
				this._onDataLoadDisableSelectors.push(jQuerySelectorString);
			},



			/*
			=============================
			SELECTION UPDATE METHODS
			=============================
			*/
			updateSelection: function (e)
			{
				var scope = e[this.SCOPE];

				switch (scope)
				{
					case this.SCOPE_LEVEL_1_NO_PROPOGATION:
						this.updateSelectionLevel1(e, false);
						break;

					case this.SCOPE_LEVEL_1:
						this.updateSelectionLevel1(e, true);
						break;

					case this.SCOPE_LEVEL_2:
						this.updateSelectionLevel2(e);
						break;

					case this.SCOPE_LEVEL_3:
						this.updateSelectionLevel3(e);
						break;
				}
			},



			/*
			* Process level 1 (range) selection
			*
			* This is called remotely by ANY element that facilitates addition / removal of ranges to users search
			*/
			updateSelectionLevel1: function (e, updateLevel2Selection)
			{
				// EVENT FORMAT :: [test event matching internal test event params (coming straight from flash)]
				//exampleEvent = 
				//{
				//	type		: "ITEM_SELECTION_EVENT",
				//	scope		: "SCOPE_LEVEL_1",		// "SCOPE_LEVEL_1" || "SCOPE_LEVEL_2" :: This should only ever be "SCOPE_LEVEL_1" at this point
				//	select		: true,					// true || false
				//	level1Id	: 54,					// uint
				//	level2Id	: -1,					// uint
				//	level3Id	: -1					// uint
				//};
				
				this._alertEventUpdateSelection("updateSelectionLevel1", e);

				

				if (updateLevel2Selection)
				{
					// Pass event into all registered 'model scope' data display host instances
					// This generally causes a level 2 display to fully synch all level2 items to match level1 status if level1 ids match
					this.updateSelectionLevel2(e);
				}


				// PLEASE NOTE : 'LEVEL-1 : range scope' data display instances are recreated by host class once data returned from AJAX call
				// Configure AJAX call to generate NEW displays



				// Trigger all registered LEVEL-1 ('range scope') data display host instances to decouple, remove and destroy their swf instances 
				var a = this._swfDataDisplaysScopeLevel1;

				for (i = 0; i < a.length; i++)
				{
					a[i].enterLoadingState();
				}


				// Enter loading state
				this._enterDataLoadingState();


				// Pass update into non-swf-data display listeners who are listening for events at level 1
				a = this._listenersLevel1;
				for (var i = 0; i < a.length; i++)
				{
					a[i].handleItemSelectionUpdate(e);
				}


				//
				// TODO ::
				//
				// TRIGGER AJAX CALL - SEE SIMULATION FOR EVENT HANDLER EXAMPLE
				//
				//
				//mrm.runtime.display.displayManager._test_handleAjaxDataLoadedLevel1({ empty: "TEMP EXAMPLE - empty object" });

								
				//
				//
				//
				//this._setupDataLoadedSimulation();
				//
				//
				//

			},



			/*
			* Process level 2 (model) selection
			*
			* This is called remotely by ANY element that facilitates addition / removal of models to users search
			*/
			updateSelectionLevel2: function (e)
			{
				// EVENT FORMAT :: [test event matching internal test event params (coming straight from flash)]
				//exampleEvent = 
				//{
				//	type		: "ITEM_SELECTION_EVENT",
				//	scope		: "SCOPE_LEVEL_2",		// "SCOPE_LEVEL_1" || "SCOPE_LEVEL_2" :: This can be either as each will be handled correctly in swf - will be level_1 when called from 'updateSelectionLevel1()'
				//	select		: true,					// true || false
				//	level1Id	: 54,					// uint
				//	level2Id	: 2,					// uint
				//	level3Id	: -1					// uint
				//};

				this._alertEventUpdateSelection("updateSelectionLevel2", e);

				// Pass event into all registered SWF data display host instances
				var a = this._swfDataDisplaysScopeLevel2;
				for (var i = 0; i < a.length; i++)
				{
					a[i].handleItemSelectionUpdate(e); // Test for JS created event: // a[i].handleItemSelectionUpdate(exampleEvent);
				}


				// Pass update into NON-SWF-data display listeners who are listening for events at level 2
				a = this._listenersLevel2;
				for (var i = 0; i < a.length; i++)
				{
					a[i].handleItemSelectionUpdate(e);
				}


				// Pass update into non-swf-data display listeners who are listening for events at any level
				a = this._listenersAllLevels;
				for (var i = 0; i < a.length; i++)
				{
					a[i].handleItemSelectionUpdate(e);
				}



				if (e.scope == this.SCOPE_LEVEL_2)
				{
					//
					// TODO ::
					//
					// TRIGGER AJAX CALL - ONLY - IF e.scope = "SCOPE_LEVEL_2";
					//
					//
				}


			},



			/*
			* Process level 3 (derivative) selection
			*
			* This is called remotely by ANY element that facilitates addition / removal of derivatives to users search
			*
			* Simply updates user search setting on the server via AJAX - no need to update the UI or update any other elements
			*/
			updateSelectionLevel3: function (e)
			{
				// EVENT FORMAT
				//exampleEvent = 
				//{
				//	type		: "ITEM_SELECTION_EVENT",
				//	scope		: "SCOPE_LEVEL_3",		// "SCOPE_LEVEL_3"
				//	select		: true,					// true || false
				//	level1Id	: 1,					// uint
				//	level2Id	: 2,					// uint
				//	level3Id	: 3						// uint
				//};

				this._alertEventUpdateSelection("updateSelectionLevel3", e);



				//
			},



			/*
			=============================
			PRIVATE MEMBERS
			=============================
			*/
			/*
			=============================
			REGISTERED LISTENER STORAGE COLLECTIONS
			=============================
			*/
			// swf data displays
			_swfDataDisplaysScopeLevel1: [],
			_swfDataDisplaysScopeLevel2: [],

			// jsControlClass instances
			_listenersAllLevels: [],
			_listenersLevel1: [],
			_listenersLevel2: [],

			// disable 'on data load'
			_onDataLoadDisableSelectors: [],



			/*
			=============================
			BROADCAST (to listener) METHODS
			=============================
			*/
			/*
			* Broadcast selection summary update
			*
			* Allows Level 2 displays to be updated once new Level 1 data has been loaded from server
			* - On range update selected status of the Level 2 displays is instantly updated via 'updateSelectionLevel1() calling updateSelectionLevel2()'
			* - This updates the Level 2 displays to reflect updated search parameters
			*/
			_broadcastSelectionSummaryUpdate: function (e)
			{
				//exampleEvent = 
				//{
				//	dataCategory	: "DATA_CATEGORY_PRICE",
				//	dataScope		: "SCOPE_LEVEL_1",			// "SCOPE_LEVEL_1" || "SCOPE_LEVEL_2" || "SCOPE_LEVEL_3"
				//	dataId			: -1,						// For level 2 updates set to Range Id otherwise set to either 0 or -1 as ignored
				//	
				//	selectableMax	: 300000,
				//	selectableMin	: 50000,
				//	selectedMax		: 250000,
				//	selectedMin		: 15000
				//}

				//alert("> _broadcastSelectionSummaryUpdate <\n dataCategory = " + e["dataCategory"] + "\n dataScope = " + e["dataScope"] + "\n dataId = " + e["dataId"] + "\n selectableMin = " + e["selectableMin"] + "\n selectableMax = " + e["selectableMax"] + "\n selectedMax = " + e["selectedMax"] + "\n selectedMin = " + e["selectedMin"]);

				// Update ONLY Level-2 (model) scope items (Level-1 (range) scope totally regenerated)
				var a = this._swfDataDisplaysScopeLevel2;
				for (var i = 0; i < a.length; i++)
				{
					a[i].handleSelectionSummaryUpdate(e);
				}
			},


			/*
			* Broadcast a ValueSelectionEvent into ALL registered swfDataDisplayHost JsClass instances (who in turn pass event into swf)
			*
			* @param e [ValueSelectionEvent (AS)]	e is an object whose form should mimic the associated AS class definition
			*/
			_broadcastValueSelectionUpdate: function (e)
			{
				// Get all flash element host JsClass instances and update :: both range and model scope
				// Update each instance of 'mrm.common.display.views.DataDisplay'

				var a;
				var i;

				a = this._swfDataDisplaysScopeLevel1;
				for (i = 0; i < a.length; i++)
				{
					a[i].handleValueSelectionUpdate(e);
				}

				a = this._swfDataDisplaysScopeLevel2;
				for (i = 0; i < a.length; i++)
				{
					a[i].handleValueSelectionUpdate(e);
				}
			},


			/*
			* Update Level 1 listeners with new display data
			*/
			_broadcastUpdatedDisplayDataLevel1: function (data)
			{
				// Update LEVEL-1 listeners
				var a = this._swfDataDisplaysScopeLevel1;
				for (var i = 0; i < a.length; i++)
				{
					a[i].handleDisplayDataUpdate(data);
				}
			},



			/*
			=============================
			DISPLAY CONTROL
			=============================
			*/
			/*
			* Add loading state elements to all resistered html elements 
			*/
			_enterDataLoadingState: function ()
			{
				// Put all registered elements into a disabled state

				var html = "<div class='png " + this.CLASS_AUTO_DISABLE_DISPLAY + "'></div>";

				var a = this._onDataLoadDisableSelectors;
				var i;

				for (i = 0; i < a.length; i++)
				{
					var item = $(a[i]);
					item.append(html);
				}
			},



			/*
			* Remove all added loading state elements
			*/
			_exitDataLoadingState: function ()
			{
				// Re-enable all elements (remove added disable state html)
				$(("." + this.CLASS_AUTO_DISABLE_DISPLAY)).remove();
			},



			/*
			=============================
			INTERNAL DATA PROCESSING
			=============================
			*/

			/*
			* Process (new) Level 1 data loaded
			* 
			* This is the event handler for the ajax data call
			* - The data is formatted and passed to the appropriate update / process methods 
			*/
			_processDataLoadedLevel1: function (level1Data, selectionSummaryData)
			{
				// Exit data loading state
				this._exitDataLoadingState();

				// Update level 1 listeners
				this._broadcastUpdatedDisplayDataLevel1(level1Data);

				// Process (broadcast) selection summary update
				this._broadcastSelectionSummaryUpdate(selectionSummaryData);
			},



			/*
			=============================
			INTERNAL EVENT HANDLERS
			=============================
			*/



			/*
			=============================
			INTERNAL UTILITIES
			=============================
			*/

			_alertEventUpdateSelection: function (eventName, e)
			{
				var eventDesc = "called from " + eventName + "method." +
										"\n\n" +
										"type = " + e.type + ",\n" +
										"scope = " + e.scope + ",\n" +
										"select = " + e.select + ",\n" +
										"level1Id = " + e.level1Id + ",\n" +
										"level2Id = " + e.level2Id + ",\n" +
										"level3Id = " + e.level3Id + ",\n" +
										"source = " + e.source + ".";

				if (this.DEBUG)
				{
					alert(eventDesc);
				}
			},










			///////////////////////////
			// TEMP / TESTING
			///////////////////////////
			///////////////////////////
			///////////////////////////
			///////////////////////////
			///////////////////////////
			///////////////////////////
			///////////////////////////
			///////////////////////////
			///////////////////////////
			///////////////////////////


			testValueSelectionUpdate: function ()
			{
				alert("testValueSelectionUpdate :: DisplayManager");

				var o =
													{
														dataCategory: "DATA_CATEGORY_PRICE",
														minValue: 8000, //24915
														maxValue: 50000//77953
													};

				this._broadcastValueSelectionUpdate(o);
			},



			testSelectionSummaryUpdate: function ()
			{
				alert("testSelectionSummaryUpdate :: DisplayManager");

				// FULL UPDATE
				/* */
				var o =
													{
														dataCategory: "DATA_CATEGORY_PRICE",
														selectableMax: 300000,
														selectableMin: 50000,
														selectedMax: 250000,
														selectedMin: 15000
													}

				// SELECTED ONLY UPDATE
				/*
				var o = 
				{
				dataCategory	: "DATA_CATEGORY_PRICE",
				selectableMax	: 120000,
				selectableMin	: 0,
				selectedMax		: 110588,	//77953
				selectedMin		: 15035		//24915
				}
				*/

				this.processSelectionSummaryUpdate(o);
			},



			_setupDataLoadedSimulation: function ()
			{
				setTimeout(mrm.runtime.display.displayManager._setupDataLoadedSimulationHandler, 1000);
			},



			_setupDataLoadedSimulationHandler: function ()
			{
				//mrm.runtime.display.displayManager._exitDataLoadingState();
				//////////
				//////////
				//////////
				//////////
				// Simulate new data loaded
				mrm.runtime.display.displayManager._test_handleAjaxDataLoadedLevel1({ empty: "TEMP EXAMPLE - empty object" });
				//////////
				//////////
				//////////
				//////////
			},



			_test_new_level_1_data_a:
											{
												dataScope: "SCOPE_LEVEL_1",
												dataCategory: "DATA_CATEGORY_PRICE",
												externalDataIdentifier: "associated_external_data_element_ID",
												selectionSummary:
												{
													userDefinedSelection: true,
													selectedMin: 500,
													selectedMax: 35000,
													selectableMin: 500,
													selectableMax: 200000
												},
												dataSummary:
												{
													id: 0,
													min: 1000,
													max: 99999
												},
												data: [
													{
														title: "GS",
														id: 2033, 	//Model ID
														imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
														//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
														selected: false,
														min: 1000,
														max: 35000
													},


												/*
												* OTHER MODELS
												*/
															{
															title: "IS",
															id: 2035,
															imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
															//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
															selected: false,
															min: 5000,
															max: 45000
														},
															{
																title: "LS",
																id: 2034,
																imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																selected: false,
																min: 10000,
																max: 60000
															},
															{
																title: "RX",
																id: 2036,
																imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																selected: false,
																min: 10000,
																max: 60000
															},
															{
																title: "SC",
																id: 2037,
																imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																selected: false,
																min: 30000,
																max: 40000
															}
													]
											},



			_test_new_level_1_data_b:
											{
												dataScope: "SCOPE_LEVEL_1",
												dataCategory: "DATA_CATEGORY_TRANSMISSION",
												externalDataIdentifier: "associated_external_data_element_ID",
												dataSummary:
												{
													id: 0,

													gridDataCategories:
													[
														"Petrol",
														"Diesel",
														"Hybrid"
													]
												},
												data: [
													{
														title: "GS",
														id: 2033,
														imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
														//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
														selected: false,
														gridData:
														{
															"Petrol": 1044,
															"Diesel": null,
															"Hybrid": 50
														}
													},


												/*
												* OTHER MODELS
												*/
														{
														title: "IS",
														id: 2035,
														imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
														//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
														selected: false,
														gridData:
															{
																"Petrol": 10,
																"Diesel": null,
																"Hybrid": null
															}
													},

															{
																title: "LS",
																id: 2034,
																imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																selected: false,
																gridData:
																{
																	"Petrol": null,
																	"Diesel": 5,
																	"Hybrid": 100
																}
															},

															{
																title: "RX",
																id: 2036,
																imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																selected: false,
																gridData:
																{
																	"Petrol": null,
																	"Diesel": 5,
																	"Hybrid": 100
																}
															},

															{
																title: "SC",
																id: 2037,
																imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																selected: false,
																gridData:
																{
																	"Petrol": null,
																	"Diesel": null,
																	"Hybrid": 100
																}
															}
												]

											},

			/*
			* Ajax data loaded handler : new Level 1 data
			* 
			* This is the event handler for the ajax data call
			* - The data is formatted and passed to the appropriate update / process methods 
			*/


			_test_handleAjaxDataLoadedLevel1: function (ajaxData)
			{
				var dataLevel1_a = this._test_new_level_1_data_a;

				//////////////////////////////////////////////////////////////////////////////////
				// EVENT FORMATS UPDATED -- SEE 'process method'
				/////////////////////////////////////////////////////////////////////////////////

				// Generate new selection summary data object from data
				var example_selectionSummaryData_a =
															{
																dataCategory: dataLevel1_a.dataCategory,
																selectableMax: dataLevel1_a.selectionSummary["selectableMax"],
																selectableMin: dataLevel1_a.selectionSummary["selectableMin"],
																selectedMax: dataLevel1_a.selectionSummary["selectedMax"],
																selectedMin: dataLevel1_a.selectionSummary["selectedMin"]
															}

				// Process data
				this._processDataLoadedLevel1(dataLevel1_a, example_selectionSummaryData_a);



				var dataLevel1_b = this._test_new_level_1_data_b;

				// Generate new selection summary data object from data
				var example_selectionSummaryData_b =
															{
																dataCategory: undefined,
																selectableMax: undefined,
																selectableMin: undefined,
																selectedMax: undefined,
																selectedMin: undefined
															}

				// Process data
				this._processDataLoadedLevel1(dataLevel1_b, example_selectionSummaryData_b);

			}



			///////////////////////////
			///////////////////////////
			///////////////////////////
			///////////////////////////
			///////////////////////////
			///////////////////////////
			///////////////////////////
			///////////////////////////
			///////////////////////////
			///////////////////////////


		}
	);



	//alert("mrm.common.search.displayManager ::  Class definition successful");
