﻿
/// <reference path="../../../../jQuery/1.3.2/jquery-1.3.2-vsdoc.js" />

/**
 *
 * SearchConfiguration
 *
 * This class manages the search configuration status within the client environment
 *
 * Setups up search configuration elements such as sliders, image controls, validation, server search criteria update
 * and dynamic stock count.
 *
 * Author : Marc Lancashire
 */

	// Check that namespace into which the Class definition will be creates has been defined & if not then create
	
	if (!mrm.global.isNamespaceDefined("mrm.lexus.display")) mrm.global.createNamespace("mrm.lexus.display", "1.0");

	// Class definition : 

	mrm.lexus.display.SearchConfiguration = mrm.common.display.SearchConfiguration.subClass
	(
		{
			/*
			=============================
			CONSTANTS
			=============================
			*/
			
				"DATA_CATEGORY_PRICE"			: "DATA_CATEGORY_PRICE",
				"DATA_CATEGORY_MILEAGE"			: "DATA_CATEGORY_MILEAGE",
				"DATA_CATEGORY_FUELTYPE"		: "DATA_CATEGORY_FUELTYPE",
				"DATA_CATEGORY_TRANSMISSION"	: "DATA_CATEGORY_TRANSMISSION",
				
				"QUICKSEARCH_FORM_ID"			: "QuickSearchForm",
				
				"SELECTOR_PRICE"			: "div.priceto select.mp-control-data",
				"SELECTOR_MILEAGE"			: "div.odometerto select.mp-control-data",
				"SELECTOR_FUELTYPE"			: "div.transmission input.mp-control-data",
				"SELECTOR_TRANSMISSION"		: "div.fueltype input.mp-control-data",
				
				"EVENT_GRAPH_SELECTION_CHANGE"	: "change.graph-selection-change",
				
				
				"SELECTOR_FORM_SUBMITS"		: "div.validatePostcode",
				"SELECTOR_STOCK_COUNT"		: "#ctl00_spnCount",
				
				"SELECTOR_SEARCH_LOCATION_CONTAINER" : "form#SearchCriteria > div.search-location-panel-container fieldset.search-location-fieldset",
				
				"SELECTOR_INPUT_POSTCODE" : "div.postcode input.postcode",
			
				"SELECTOR_SELECT_DISTANCE" : "div.distance select.mp-control-data",
			
			
			
			
			/*
			 =============================
			 CONSTRUCTOR
			 =============================
			 */
				"init" : function (instanceReferenceString)
				{
					this.instanceString = instanceReferenceString;
				},
			
			
			
			/*
			 =============================
			 CONFIGURATION PROPERTIES (instance configuration)
			 =============================
			 */
				"instanceString" : undefined,
				
				"callbackUtilities" : {},
				
			
			/*
			=============================
			PUBLIC MEMBERS
			=============================
			*/
				
				"bind" : function(jqContainer, containerTargetString, loadEnhancerClassInstance)
				{
					this._super(jqContainer); // call base bind
					
					var __this = this;
					
					var containerTargetString = ((containerTargetString != null) ? containerTargetString : "body");
					
					if (loadEnhancerClassInstance)
					{
						var formContainers		= jqContainer.filter("form");
						
						var nonFormContainers	= jqContainer.filter(":not(form)");
						
						formContainers.bind("submit", function (e){__this._displayLoadingState(e, loadEnhancerClassInstance)});
						
						nonFormContainers.each(
							function (i)
							{
								item = $(this);
								var closestParentForm = item.closest("form");
								closestParentForm.bind("submit", function (e){ __this._displayLoadingState(e, loadEnhancerClassInstance) });
							}
						);
						
					}
					
					
					// Add form submit click functionality to search button
					
					var buttons = jqContainer.find(this.SELECTOR_FORM_SUBMITS);

//						
// [ sIFR button ] activation
//					
//					if ($.browser.msie)
//					{
//						// Create form reference storage array
//						this.jQueryFormObjects = [];
//						
//						// Format link string fragment
//						var linkStringFragment = "javascript:" + this.instanceString + ".handleSifrLinkInternalClick(";
//						
//						// Process buttons
//						buttons.each 
//						(
//							function (i)
//							{
//								var ___this = $(this);
//								
//								// Find child link
//								var link	= ___this.find("a");
//								
//								// Find parent form
//								//var parentForm = ___this.parents("form:first");
//								var parentForm = ___this.closest("form");
//								
//								// Store parent form in reference array
//								__this.jQueryFormObjects.push(parentForm);
//								
//								// Attach href
//								link.attr("href", (linkStringFragment + i + ");"));
//							}
//						)
//					}
					
					
					
					//jqContainer.find(this.SELECTOR_FORM_SUBMITS).bind("click.form-submit", null, function(e) { __this.OnSearchFormSubmit(e); });
					buttons.bind("click", null, function(e) { __this.OnSearchFormSubmit(e); });
					
//
// [ sIFR button ] styling
//					
//					// Style any buttons [ nb: 'this.SELECTOR_FORM_SUBMITS' is actually targeting for buttons tagged as (".validatePostcode") ]
//					sIFR.runDelayedButtonStyling(containerTargetString + " " + this.SELECTOR_FORM_SUBMITS + " " + sIFR.styles.DEFAULT_BUTTON_STYLE_TARGET_STRING_INTERNAL_PATH);
					
					
					
					// add lexus graph item selection change binds
					
					// price
					if (window.json_priceData_level_1)
					{
						jqContainer.find(this.SELECTOR_PRICE).bind(this.EVENT_GRAPH_SELECTION_CHANGE, {hasSummary:true,levelSource:json_priceData_level_1}, function(e){ __this._changeDataDisplaySelection(__this.DATA_CATEGORY_PRICE,e); });
					}
					
					// mileage
					if (window.json_odometer_level_1)
					{
						jqContainer.find(this.SELECTOR_MILEAGE).bind(this.EVENT_GRAPH_SELECTION_CHANGE, {hasSummary:true,levelSource:json_odometer_level_1}, function(e){ __this._changeDataDisplaySelection(__this.DATA_CATEGORY_MILEAGE,e); });
					}
					
					// fuel type
					if (window.json_fuelType_level_1)
					{
						jqContainer.find(this.SELECTOR_FUELTYPE).bind(this.EVENT_GRAPH_SELECTION_CHANGE, {hasSummary:false,levelSource:json_fuelType_level_1}, function(e){ __this._changeDataDisplaySelection(__this.DATA_CATEGORY_FUELTYPE,e); });
					}
					
					// transmission type
					if (window.json_transmissionData_level_1)
					{
						jqContainer.find(this.SELECTOR_TRANSMISSION).bind(this.EVENT_GRAPH_SELECTION_CHANGE, {hasSummary:false,levelSource:json_transmissionData_level_1}, function(e){ __this._changeDataDisplaySelection(__this.DATA_CATEGORY_TRANSMISSION,e); });
					}
				},
				
				
				
					/*
					=============================
					IE 6 : Sifr'd link click handling method
					=============================
					*/
						"jQueryFormObjects" : undefined,
						
						
						"handleSifrLinkInternalClick" : function (id)
						{
							var form = this.jQueryFormObjects[id];
							
							// Escape if no form
							if (!form) return;
							
							// Create event object
							var e		= new jQuery.Event("click"); 
							e.target	= e.currentTarget = form[0];
							
							// Run method
							this.OnSearchFormSubmit(e)
						},
				
				// override base adding bind of postcode
				"bindDataElement" : function(jqDataElement)
				{
					this._super(jqDataElement); // call base bind
					
					var __this = this;
					
					jqDataElement.bind("change.map-refresh", null, function (e) { __this._handlePostcodeChange(e); });
				},
				
				
				"bindLocationMapFeature" : function (locationMapInstance)
				{
					// Store internal reference
					this._locationMapInstance = locationMapInstance;
					
					// Local instance 'hook' reference
					var __this = this;
					
					// Find postcode container
					var container = $(this.SELECTOR_SEARCH_LOCATION_CONTAINER);
					
					//
					// USE 'Change' events as these will be fired when input loses focus AFTER IT HAS BEEN CHANGED
					//
					// Find "postcode input" within "postcode container"
					var pInput = container.find(this.SELECTOR_INPUT_POSTCODE);
					// Bind to change event
					pInput.bind("change.map-refresh", null, function (e) { __this._handlePostcodeChange(e); });
					
					// Find slider control within "postcode container"
					var sDistance = container.find(this.SELECTOR_SELECT_DISTANCE);
					// Bind to change event
					sDistance.bind("change.map-refresh", null, function (e) { __this._handleDistanceChange(e); });
				},

				"ValidateInput" : function(jqDataElement, throwError)
				{
					// validate the postcode
					var isValid = this.ValidatePostcode(jqDataElement, throwError);
					
					// now we've validated the postcode field we need to ensure that there is a model selected, first we need to see what state we're in tho
					if ((jqDataElement[0].id == this.QUICKSEARCH_FORM_ID) && (jqDataElement.find('input:checked').length == 0)) {
						isValid = false;
					}	
					
					// check for the hidden selected models field, if this is present but empty then stop the search from progressing
					var input = $('input.selected-models');
					if((input.length > 0) && (input.val() == '')) {
						isValid = false;
					}
					
					return isValid;
				},
				
				"ValidatePostcode" : function(jqDataElement, throwError)
				{
					// validate the postcode
					var isValid = true;
					var formElement = (jqDataElement.is("form"))? jqDataElement : jqDataElement.closest(this.SELECTOR_FORM);
					var postcodes = formElement.find("input.postcode");		
								
					var postCodeStatus = postcodes.parent().find(".lookup-status");
					if (postcodes.length > 0 && postCodeStatus.length > 0)
					{
						isValid = postCodeStatus.hasClass("lookup-valid");
					}

					/*if (postcodes.length > 0 && mrm.global.utilities.validatePostcode)
					{
						// has postcode
						var postcode = postcodes.val();
						var formattedPostcode = mrm.global.utilities.validatePostcode(postcode)
						isValid = (formattedPostcode != null);
						
						if(isValid)
						{
							//postcodes.unbind();
							
							postcodes.val(formattedPostcode);
							
							var __this = this;
							
							//this.bindDataElement(postcodes);
						}
					}*/

					return isValid;
				},
				
				// carries out a search criteria change event
				"OnDataElementChange": function(event)
				{
					if (!$(event.currentTarget).hasClass("postcode"))
					{
						this._super(event); // call base
					}
				},
				
				// called when the users search criteria is invalid, called from form submission and criteria change
				"OnInvalidInput": function(jqFormElement, jqDataElement, throwError)
				{
					var _this = this;
					
					this._super(jqFormElement, jqDataElement, throwError); // call base
					
					var containerTargetString = '.ui-lightbox-container div#dvInvalidSearchWarning';
					
					if (throwError)
					{
						// Launch error msg the lightbox
						uiBox_Trigger("#?go=go&width=300&height=160&target=divUvlContainer&source=dvInvalidSearchWarning&displayPosition=viewableCentre");
						
						// Bind the continue button
						var dialogContainer = $(containerTargetString);
						
						var continueButton = dialogContainer.find("div.button-continue");
						
						continueButton.click( function (e) { _this._handleDialogueButtonClick(); } );
						dialogContainer.click(function (e) { _this._handleDialogueButtonClick(); });
//
// [ sIFR button ] activation / styling
//
//
//						// If ie then add href attribute to each buttons internal <a> tag
//						if ($.browser.msie)
//						{
//							var continueLink	= continueButton.find("a");
//							
//							continueLink.attr("href", "javascript:" + this.instanceString + "._handleDialogueButtonClick();");
//						}
//						
//						// Style buttons
//						sIFR.runDelayedButtonStyling(containerTargetString + " " + "div.button-style-1" + " " + sIFR.styles.DEFAULT_BUTTON_STYLE_TARGET_STRING_INTERNAL_PATH);
						
					}
				},
				
				
				"OnStockCountChange" : function(stockCount)
				{
					this._super(stockCount); // call base
					
					//rebind sIFR result count
					/* not required yet, only if we start binding the header result count, at the moment it on changes on change of result tool set.
				    if (sIFR && sIFR.styleResultsListResultsCount)
				    {
						sIFR.styleResultsListResultsCount();
					}
					*/
				},
				
				
			
			
			/*
			=============================
			INTERNAL MEMBERS
			=============================
			*/
				
				"_locationMapInstance" : undefined,
				
			
				/*
				 =============================
				 INTERNAL EVENT HANDLERS
				 =============================
				 */
					"_handleDialogueButtonClick" : function ()
					{
						uiBox_Hide();
					},
					
					
					"_handlePostcodeChange" : function (e)
					{
						
						var inputControl = $(e.target);
						
						// validate postcode
						var isValidPostcode = this.ValidatePostcode(inputControl, false);
						
						// alert("Postcode updated....... isValidPostcode = " + isValidPostcode);

						if (isValidPostcode)
						{
							// valid so ajax get new data set & update map feature
							
							/*######################## Force Bind Stock Count ########################*/
							// i think this needs moving into _handlePostcodeChangeSuccess
							this.GetStockCountNow(inputControl);
							/*######################## Below Should Go In A Function ########################*/
							
							// get parent form
							var formElement = inputControl.parents(this.SELECTOR_FORM);

							// get work flow key from mp-sync-key data item in form
							var wflw = this._workflowKey(formElement,"_lo_vi");

							// setup ajax call
							$.ajaxManager.clearArguments();

							$.ajaxManager.ajaxSettings.arguments.add(this.ARGUMENT_WORKFLOW, wflw);

							// add search criteria arguments to ajax call
							// set url
							$.ajaxManager.updateUrl($.ajaxManager.ajaxSettings.arguments.getString("&"));

							var currentScope = this;

							// bind before send
							//$.ajaxManager.onBeforeSend = function() { currentScope.OnSyncBefore() };

							// bind error
							$.ajaxManager.onError = function(XMLHttpRequest, textStatus, errorThrown) { currentScope.OnSyncError(XMLHttpRequest, textStatus, errorThrown) };

							// bind success
							$.ajaxManager.onSuccess = function(p_response) { currentScope._handlePostcodeChangeSuccess(p_response) };

							// fire ajax request
							$.ajaxManager.makeRequest();

						}
						else 
						{
							// invalid so update map with invalid status
							this._locationMapInstance.processInvalidLocationUpdate();
						}
					},
					
					"_handlePostcodeChangeSuccess" : function(p_response) {

							this._debugtrace("_handlePostcodeChangeSuccess:{" + p_response + "}");

							var result = eval(p_response);
							
							this.callbackUtilities.processResultControls(result);

							// imitate a data change
//							window.locationMapData.centreData[0].centreName = "Lexus Newcastle Updated";

							// update map feature
							this._locationMapInstance.processDataUpdate(window.locationMapData);

//							this.OnStockCountChange(p_response);
							
//							this._super(p_response);
														
							return;
						},

					"_handleDistanceChange" : function (e)
					{
						//alert("hello : Distance has changed.......");
						
						// Resolve select control
						var selectControl = $(e.target);
						
						// Find selected option
						var selectedOption = selectControl.find("option:selected:first");						
						
						// Get distance : read value from selected option
						var distance = selectedOption.val();
						
						// Pass new distance into mapFeatureInstance
						this._locationMapInstance.processDistanceUpdate(distance);
					},
				
			
			
				/*
				=============================
				HELPER METHODS
				=============================
				*/
					"_displayLoadingState" : function (e, loadEnhancerClassInstance)
					{
						var target = $(e.target);
						
						// To view loading state stop event propagation and hence stop the form submit
						// e.preventDefault();
						// e.stopPropagation();
						
						target.addClass("SEARCH-FORM-AUTO-LOADING-STATE");
						
						loadEnhancerClassInstance.createLoadingState(target);
					},
					
					
					
					"_changeDataDisplaySelection" : function(displayDataType,event)
					{
						// create empty summary if we don't need to
						var summaryData = this._createSummaryData(null, null, null, null, null);
						
						if (event.data.hasSummary == true && event.data.levelSource != null)
						{
							var dataElement = event.target;
							var currentMin;
							var currentMax;
							var selectedMax;
							var selectedMin;
							var selectableMax;
							var selectableMin;
							
							// find selectable min  and selectable max values for the x axis
							var levelData			= event.data.levelSource;
							var levelDataItems		= levelData.data;
							for (var i = 0; i < levelDataItems.length; i++)
							{
								var itemMin = levelDataItems[i].min;
								var itemMax = levelDataItems[i].max;
								currentMin = (currentMin)? Math.min(currentMin, itemMin) : itemMin;
								currentMax = (currentMax)? Math.max(currentMax, itemMax) : itemMax;
							}
							// get selected values from data field
							selectedMin = dataElement.options[0].value;
							selectedMax = dataElement.options[dataElement.selectedIndex].value;
							
							// calc the selectable min
							var selectableMin = Math.min(currentMin,selectedMin);
							selectedMin = selectableMin; // as we only have "to" fields selected min is always selectable min
							
							// calc the selectable max
							selectableMax = Math.max(currentMax,selectedMax);
							
							// create event data
							summaryData = this._createSummaryData(levelData.dataCategory, levelData.dataScope, levelData.dataSummary.id, selectableMin, selectableMax, selectedMin, selectedMax);
						}
						
						// use display manager so that new data is pushed into all control that are listerning for this update
						if (mrm.runtime.display.displayManager)
						{
							//alert("sending event\ndc = " + summaryData.dataCategory + "\nds = " + summaryData.dataScope + "\nid = " + summaryData.dataId + "\nmin = " + summaryData.selectableMin + "\nmax = " + summaryData.selectableMax + "\nsmin = " + summaryData.selectedMin + "\nsmax = " + summaryData.selectedMax);
							mrm.runtime.display.displayManager._broadcastValueSelectionUpdate(summaryData);
						}
					},
					
					"_createSummaryData" : function(dataCategory,dataScope,dataId,selectableMin,selectableMax,selectedMin,selectedMax)
					{
						var summaryEvent = {};
						
						summaryEvent.dataCategory	= dataCategory;
						summaryEvent.dataScope		= dataScope;
						summaryEvent.dataId			= dataId;
											
						summaryEvent.minValue		= selectedMin;
						summaryEvent.maxValue		= selectedMax;
						
						summaryEvent.selectableMin	= selectableMin;
						summaryEvent.selectableMax	= selectableMax;
						
						summaryEvent.selectedMin	= selectedMin;
						summaryEvent.selectedMax	= selectedMax;
						
						return summaryEvent;
					},
					
					"_stub" : "stub"
		}
	);
