/// <reference path="C:\References\jquery-1.4.1-vsdoc.js" />

// ********************************************************************
// 
// Manheim Retail Marketing
// ********************************************************************
// Copyright © 2010 Manheim Retail Marketing.
//
//  Summary
// ******************************
// $Workfile: SearchConfiguration.js $
// Notes:		This class manages the search criterion on the server enviroment
//
//				Hooks up the change event on mp-control-data control, via ajax:
//					- Validates search criteria selection.
//					- Re-binds user search on the their session on the server.
//					- Responds with a stock count of their current search crition selection.
//					- Refreshs ui diplay with stock count.
//	
//				Based on a custom manufacturer implementation.
//
// File History Information
// ************************
// Created on:					    30/03/2010 12:10
// Last Modified:					$Modtime: 3/09/10 9:42 $
// Original Author:					Marc Lancashire
// Last Modified by:				$Author: Prescottl $
// Last JS Lint:					07/12/2009 11:40
//
// Source Control Information
// **************************
// File Version:					$Revision: 15 $
// VSS Location:					$Archive: /Manheim.Portfolio/Manheim.Portfolio.Web.UI.Client.Assets/assets/js/mrm/lib/ui/controls/1.0/SearchConfiguration.js $
//
// ********************************************************************

// Check / create namespace
if (!mrm.global.isNamespaceDefined("mrm.lib.ui.controls"))
{
	mrm.global.createNamespace("mrm.lib.ui.controls", "1.0");
}


// Class definition
mrm.lib.ui.controls.SearchConfiguration = mrm.lib.ui.controls.BaseControl.subClass
(
{
	
	/*
	=============================
	CONSTANTS
	=============================
	*/
	"BINDER_NAME"						: "SearchConfiguration",
	
	"TRACE_PREFIX"						: "mrm.lib.ui.controls.SearchConfiguration",
	
	"SELECTOR_CONTROL"					: "form.mp-search-count", // please add selector, this is used to filter the bindable controls
	
	"HANDLER_URL"						: "/Handlers/cta.ashx",
	"ARGUMENT_WORKFLOW"					: "wflw",
	"ARGUMENT_COUNT"					: "count",
	"WORKFLOW_ACTION"					: "_re_pr",
	"DEFAULT_MODULE"					: "se_na",
	
	"MODE_ENABLE_STOCK_COUNT"			: true,
	"MODE_ALLWAYS_BIND"					: false,
	"MODE_BIND_DATACOUNTERS"			: false,
	
	"SELECTOR_FORM"						: "form.mp-search-count",
	"SELECTOR_BIND_INPUTS"				: "input.mp-control-data, select.mp-control-data",
	"SELECTOR_DATA_INPUTS"				: "input:text.mp-control-data, select.mp-control-data, input:checked.mp-control-data, input:selected.mp-control-data, input[type = 'hidden'].mp-control-data",
	"SELECTOR_DATACOUNTERS"				: "div.mp-stock-count, span.mp-stock-count",
	"SELECTOR_FORM_SUBMIT"				: "div.mp-search-submit",

	"ASYNC_WORK_FLOW_TIMER"				: 0,
	"SEARCH_SYNC_DELAY"					: 500,
	
	"DEFAULT_INPUT_VALIDATION_RESULT"	: true,
	"DEFAULT_STATE"						: "...",
	
	"UTILITY_WORKFLOW"					: null,
	"AJAX_MANAGER"						: null,
	
	// event names
	//"E_CALL_BACK_COMPLETE"				: "MRM-SYNC-CALLBACK-COMPLETE",

	"COMPLETE_EVENT_TRIGGER"			: "MRM-SEARCH-CONFIGURATION-COMPLETE",
	
	"MRM_STOCK_COUNT_REFRESH"			: "MRM-STOCK-COUNT-REFRESH",
	"MRM_DATA_ELEMENT_CHANGE"			: "MRM-DATA-ELEMENT-CHANGE",
	
	/*
	=============================
	CONSTRUCTOR
	=============================
	*/
	"init" : function (tracing, settings)
	{
		this._super(tracing, settings); // call base init
		
		// set default workflow utility
		if (mrm.global.Utilities.workflow)
		{
			this.UTILITY_WORKFLOW = mrm.global.utilities.workflow;
		}
		else if(mrm.global.isClassDefined("mrm.lib.utilities.Workflow"))
		{
			this.UTILITY_WORKFLOW = new mrm.lib.utilities.Workflow();
		}
		
		// set default ajax manager
		if ($.ajaxManager)
		{
			this.AJAX_MANAGER = $.ajaxManager;
		}
	},
	
	/*
	=============================
	PUBLIC MEMBERS
	=============================
	*/
	
	// triggers a submit event on parent form
	"onSearchSubmitControlClick" : function (jqEvent)
	{
		$(jqEvent.currentTarget).closest("form").trigger("submit");
	},
	
	// handler for a submit event on a search form, event can be raised from a form or a child element
	"onSearchFormSubmit" : function (jqEvent)
	{
		this.tracing().addTrace("OnSearchFormSubmit");
		
		var jqCurrentTarget = $(jqEvent.target);
		
		// ensure we get a form either from the event or from locating the closest form to the element that triggered the submit
		var jqFormElement = (jqCurrentTarget.is("form")) ? jqCurrentTarget : jqCurrentTarget.closest("form");
		
		var isValid = this.validateInput(jqEvent, jqFormElement, true);
		
		if (!isValid)
		{
			jqEvent.preventDefault();
			
			this.onInvalidInput(jqEvent, jqFormElement, jqCurrentTarget, true);
		}
		
		return isValid;
	},
	
	
	// handler for a change event on a data element
	"onDataElementChange" : function (jqEvent)
	{
		this.tracing().addTrace("OnDataElementChange");
		
		var jqDataElement = $(jqEvent.target);
		
		jqDataElement.trigger(this.MRM_DATA_ELEMENT_CHANGE);

		if (this.MODE_ALLWAYS_BIND || this.validateInput(jqEvent, jqDataElement, false))
		{
			this.getStockCount(jqEvent, jqDataElement);
		}
		else
		{
			this.onInvalidInput(jqEvent, null, jqDataElement);
		}
	},
	
	
	// clear the timer that triggers the ajax stock count
	"onClearDataRequestTimeout" : function (jqEvent)
	{
		clearTimeout(this.ASYNC_WORK_FLOW_TIMER);
	},
	
	// stub hander for search form validation
	"validateInput" : function (jqEvent, jqDataElement, throwError)
	{
		this.tracing().addTrace("ValidateInput");

		return this.DEFAULT_INPUT_VALIDATION_RESULT;
	},
	
	// stub handler for search form validations that are invalid
	"onInvalidInput" : function (jqEvent, jqFormElement, jqDataElement, throwError)
	{
		this.tracing().addTrace("Invalid Input");
	},
	
	// carries out a delayed stock count and search criteria re-sync
	"getStockCount" : function (jqEvent, jqDataElement)
	{
		this.tracing().addTrace("GetStockCount");

		clearTimeout(this.ASYNC_WORK_FLOW_TIMER);

		// scope
		var __this = this;

		this.ASYNC_WORK_FLOW_TIMER = setTimeout(
			function ()
			{
				__this._syncSearchCriteria(jqEvent, jqDataElement);
			},
			this.SEARCH_SYNC_DELAY
		);
	},
	
	// carries out an imedate stock count and search criteria re-sync
	"getStockCountNow" : function (jqEvent, jqDataElement)
	{
		this._syncSearchCriteria(jqEvent, jqDataElement);
	},
	
	// raised on change of the stock count
	"onStockCountChange" : function (jqEvent, stockCount)
	{
		this.tracing().addTrace("Stock Count = " + stockCount + ".");

		if (this.MODE_BIND_DATACOUNTERS)
		{
			this._updateDataCounters(jqEvent, stockCount);
		}
	},


	/*
	=============================
	PUBLIC SYNC METHODS
	=============================
	*/

	"onSyncBefore" : function (jqEvent)
	{
		this.tracing().addTrace("OnSyncBefore");
		
		this._updateDataCounters(jqEvent, this.DEFAULT_STATE);
	},

	"onSyncError" : function (jqEvent, XMLHttpRequest, textStatus, errorThrown)
	{
		this.tracing().addTrace("OnSyncError");
		
		return;
	},

	"onSyncSuccess" : function (jqEvent, p_response)
	{
		this.tracing().addTrace("OnSyncSuccess:{" + p_response + "}");

		var result = eval(p_response), jqCurrentTarget = $(jqEvent.target), jqFormElement;
		
		var jqFormElement = (jqCurrentTarget.is("form")) ? jqCurrentTarget : jqCurrentTarget.closest("form");
		
		if(jqFormElement.length < 1)
			jqFormElement = $(document).find(this.SELECTOR_FORM);

		// process any returned controls
		this.UTILITY_WORKFLOW.processResultControls(result, true, jqFormElement);
		
		// get the stock count from the list of returned arguments
		var stockCount = this.UTILITY_WORKFLOW.findResultArgument(result, this.ARGUMENT_COUNT);
				
		this.onStockCountChange(jqEvent, stockCount);

		//trigger the search config complete event
		jqFormElement.trigger(this.COMPLETE_EVENT_TRIGGER);

		//$(jqEvent.currentTarget).trigger(this.E_CALL_BACK_COMPLETE, [p_response]);

		return stockCount;
	},
	
	/*
	=============================
	PRIVATE MEMBERS
	=============================
	*/
	
	// build a call back link control from the provided html element
	"_initControl" : function (element, instanceId, settings)
	{
		var status = false, __this = this, jqForm = $(element), jqFormDataElements;
		
		this.tracing().addTrace("Start init Search Form");
		
		jqFormDataElements = jqForm.find(this.SELECTOR_BIND_INPUTS);
		
		// ## bind form handler
		
		//
		//For any incomming form elements bind the form submit event to the validation handler:
		//
		var eventTypeFormValidate = "submit.validation";
		//Unbind
		jqForm.unbind(eventTypeFormValidate);
		//Bind
		jqForm.bind(eventTypeFormValidate, null,
			function (e)
			{
				__this.onSearchFormSubmit(e);
			}
		);

		// bind the stock count refresh to the form
		jqForm.unbind(this.MRM_STOCK_COUNT_REFRESH);
		jqForm.bind(this.MRM_STOCK_COUNT_REFRESH,
			function (jqEvent)
			{
				__this._syncSearchCriteria(jqEvent, jqForm);
			}
		);

		//
		//For any mp-search-submit control within the form, hook a click event to submit the form:
		//
		//Find submit button
		var formSubmitButton = jqForm.find(this.SELECTOR_FORM_SUBMIT);
		var eventTypeSubmit = "click.search-form-submit";
		//Unbind any existing submit event
		formSubmitButton.unbind(eventTypeSubmit);
		//Bind new submit event
		formSubmitButton.bind(eventTypeSubmit, null, 
			function (e)
			{
				__this.onSearchSubmitControlClick(e);
			}
		);
		
		if (this.MODE_ENABLE_STOCK_COUNT)
		{
			this.tracing().addTrace("Stock count enabled");
			
			// ## bind form elements handlers
			
			// for any mp-control-data control within the form, hook a change event to the stock count refresh handler
			jqFormDataElements.bind("change.stock-count", null,
				function (e)
				{
					__this.onDataElementChange(e);
				}
			);
			
			// for any mp-control-data control within the form, hook a clear event to cancel the stock count refresh
			jqFormDataElements.bind("clear.stock-count", null,
				function (e)
				{
					__this.onClearDataRequestTimeout(e);
				}
			);
		}
		
		this.tracing().addTrace("End init Search Form");
		
		status = true;
		
		return status;
	},
	
	"_syncSearchCriteria" : function (jqEvent, jqDataElement)
	{
		var __this = this;
		
		this.tracing().addTrace("_syncSearchCriteria");

		// get parent form
		var jqFormElement = (jqDataElement.is("form")) ? jqDataElement : jqDataElement.parents(this.SELECTOR_FORM);

		if(jqFormElement.length < 1)
			jqFormElement = $(document).find(this.SELECTOR_FORM);

		// get work flow key from mp-sync-key data item in form
		var wflw = this._workflowKey(jqFormElement);

		// setup ajax call
		this.AJAX_MANAGER.clearArguments();

		this.AJAX_MANAGER.ajaxSettings.arguments.add(this.ARGUMENT_WORKFLOW, wflw);

		// add search criteria arguments to ajax call
		jqFormElement.find(this.SELECTOR_DATA_INPUTS).each(
			function ()
			{
				var jqInputElement = $(this);
				__this.AJAX_MANAGER.ajaxSettings.arguments.add(jqInputElement.attr("name"), jqInputElement.val());
			}
		);
		
		// set the base url for the handler
		this.AJAX_MANAGER.ajaxSettings.requestUrl = this.HANDLER_URL;
		
		// set url
		this.AJAX_MANAGER.updateUrl(this.AJAX_MANAGER.ajaxSettings.arguments.getString("&"));

		// bind before send
		this.AJAX_MANAGER.onBeforeSend =
			function ()
			{
				__this.onSyncBefore(jqEvent);
			};

		// bind error
		this.AJAX_MANAGER.onError =
			function (XMLHttpRequest, textStatus, errorThrown)
			{
				__this.onSyncError(jqEvent, XMLHttpRequest, textStatus, errorThrown);
			};

		// bind success
		this.AJAX_MANAGER.onSuccess =
			function (p_response)
			{
				__this.onSyncSuccess(jqEvent, p_response);
			};

		// fire ajax request
		this.AJAX_MANAGER.makeRequest();
	},

	// updates the forms data counters with provided content
	"_updateDataCounters": function (jqEvent, content)
	{
		var jqCurrentTarget = $(jqEvent.target), jqFormElement;
		jqFormElement = (jqCurrentTarget.is("form")) ? jqCurrentTarget : jqCurrentTarget.closest("form");

		jqFormElement.find(this.SELECTOR_DATACOUNTERS).html(content);
	},

	"_workflowKey" : function (jqFormElement, workflowAction)
	{
		var wfa = workflowAction, wfk;
		if (!wfa)
		{
			wfa = this.WORKFLOW_ACTION;
		}
		
		wfk = this.UTILITY_WORKFLOW.getScopedWorkflowKey(jqFormElement, wfa);
		
		if (!wfk)
		{
			if(jqFormElement.find("#wfk").length > 0)
				wfk = jqFormElement.find("#wfk").val() + wfa;
			else
				wfk = this.DEFAULT_MODULE + wfa;
		}
		
		return wfk;
	}
}
);
