////////////////////////////////////////////////////////////////
// HomeNet JS Core Site Library
// Virtual Garage Class
// (c) 2010, HomeNet Automotive LLC
// Depandancies: hnsite-module-user.js
////////////////////////////////////////////////////////////////

if (typeof HNSITE == 'undefined') HNSITE = {};
if (typeof HNSITE.Modules == 'undefined') HNSITE.Modules = {};

// ***************************************
// Define our Modules.VirtualGarage namespace
// ***************************************
HNSITE.Modules.VirtualGarage = {};

// <summary>
// Performs a Virtual Garage web service - every requesting Virtual Garage method is called through this interface
// Arguments: 
//    serviceName (string): Name of the service we wish to call (must be on the accepted method list)
//    options (object): Flexible options object for passing callbacks and data to send with the request
//       -> onAjaxSuccess (function): Called on successful ajax response, needs an argument for the response. For each method calling a service, this callback  
//             will be created by that method and not directly input as any argument. Typically the calling method will accept optional success/fail callbacks
//             which are called from this constructed callback (onAjaxSuccess) so that the semantics of those callback actions are relevant to the method name called.
//       -> onAjaxError (function): Called when ajax response errors. Normally the calling method will let the user input this callback as an argument and carry 
//             it over to here but for special circumstances it may be indirectly wrapped in a constructed callback just like onAjaxSuccess.
//       -> postData (object): Simple key/pair object of post data to send with this request.
// </summary>
HNSITE.Modules.VirtualGarage.CallService = (function() {
	// Private webservice info required
	var _webservice = {
		Url: '/framework/module-virtualgarage/virtualgarage.webservices.asp', 
		ServiceList: ['removevehicle']
	};
	
	// Return the constructor function for calling a service
	return function(serviceName, options) {
		if ($j.inArray(serviceName, _webservice.ServiceList) < 0) return;
		
		var requiredData = {
			method: serviceName, 
			r: HNSITE.Utils.Stamp()
		};
		
		if (typeof options.onAjaxSuccess != 'function')
			options.onAjaxSuccess = function() {};
		if (typeof options.onAjaxError != 'function')
			options.onAjaxError = function() {};
		if (HNSITE.Utils.IsNullOrEmpty(options.postData))
			options.postData = requiredData;
		else
			options.postData = $j.extend({}, requiredData, options.postData)

		$j.ajax({
			type: 'POST',
			cache: false,
			url: _webservice.Url, 
			data: options.postData,
			error: options.onAjaxError,
			success: options.onAjaxSuccess,
			dataType: 'json'
		});
	};
})();

// <summary>
// Removes a vehicle from the users Virtual Garage 
// Options: 
//    onSuccess (function): Callback for if the current user is found to be successfully logged in
//    onFail (function): Callback for if the current user is not logged in
//    onError (function): Callback which is run if the ajax request has an error when trying to retrieve the response
// </summary>
HNSITE.Modules.VirtualGarage.RemoveVehicle = function(cacheID, options) {
	var self = this;
	
	// Validate options and callbacks
	if (typeof options != 'object')
		options = {};
	if (typeof options.onSuccess != 'function')
		options.onSuccess = function() {};
	if (typeof options.onFail != 'function')
		options.onFail = function() {};
	if (typeof options.onError != 'function')
		options.onError = function() {};
	
	// Make the service call and perform callbacks within appropriate contexts of our method name
	self.CallService('removevehicle', {
		onAjaxSuccess: function(response) {
			if (response.status == 'success')
				options.onSuccess();
			else
				options.onFail();
		}, 
		onAjaxError: options.onError, 
		postData: {cacheID: cacheID}
	});
};

// <summary>
// Helper method which can be optionally called to assist in setting up an 'Add to Virtual Garage' button with the 
// expected behaviors for handling Carvenience. Tightly coupled to our standard virtual garage setup with Carvenience so
// may not work in many situations but could at least be used as a model for reference.
// Example from a simple DIV tag triggering the launch onclick, calling from the anonymous onclick handler: 
// HNSITE.Modules.VirtualGarage.LaunchHelper($j("#meta-vehicle-vin").val(), $j(self).hasClass("virtual-garage-saved"), function() {
// 		$j(self).addClass("virtual-garage-saved").text('Saved In Virtual Garage');
// });
// Options: 
//    vehicleVin (string): Vin of the vehicle being added or triggered from if already in their garage
//    isAlreadySaved (bool): Whether or not the vehicle is already saved in their garage (do some local processing and pass in)
//    willBeAddedCallback (function): Callback run if the user is requesting to add a vehicle not in their garage and theyre already
//       logged in too so it will definitely be added, callback may change text or icons from whatever calls this to indicate its added 
//       or maybe prevent from re-triggering. No callback for adding a car and not logged in since we cant ensure they'll follow through
//       with the action.
// </summary>
HNSITE.Modules.VirtualGarage.LaunchHelper = function(vehicleVin, isAlreadySaved, willBeAddedCallback) {
	if (typeof willBeAddedCallback != 'function')
		willBeAddedCallback = function() {};
	
	if (isAlreadySaved)
		HNSITE.Modules.Carvenience.Show({ openTab: 'vg' });
	else {
		if (HNSITE.Modules.User.Account.IsLoggedIn() === true) { // logged in, but def not saved so just add it
			HNSITE.Modules.Carvenience.Show({
				openTab: 'vg', 
				openParams: {method: 'add-vehicle', vin: vehicleVin}
			});
			willBeAddedCallback();
		}
		else { // not logged in, could be saved or not saved
			HNSITE.Data.Cookies.DeleteCookie('vgAddQueue');
			HNSITE.Data.Cookies.Create('vgAddQueue', vehicleVin, {expires: 1, path: '/'});
			HNSITE.Modules.Carvenience.Show({ openTab: 'account' });
		}
	}
};

// <summary>
// Storage for any methods we create over time for Carvenience tabs related to implementing this Virtual Garage class. Each method in the
// object is independant of each other and each has its own specific, custom purpose and should match up to a specific Carvenience
// include file for the tab. These methods are specified in the Carvenience configuration where we provide a bindings function per 
// tab. When Carvenience calls the bindings for the tab, it changes the context of 'this' to refer to the parent node for the tab to 
// be able to bind everything up quickly. Carvenience tabs are created and destroyed each time via ajax so each time it's viewed it
// pulls fresh DOM content and rebinds with the method so keep in mind when designing.
// </summary>
HNSITE.Modules.VirtualGarage.Carvenience = {

	// Basic Virtual Garage
	//  -> implementation for: module-virtualgarage/carvenience-virtualgarage.asp
	VirtualGarage: function() {
		var tabSelf = $j(this).undelegate(); // important to prevent multiple bindings
		
		// Zebra stripe our vehicle rows
		var zebraStripe = function() { tabSelf.find("div.vehicle-cell").removeClass("alternate-row").filter(":odd").addClass("alternate-row"); };
		zebraStripe();
		
		// If jScrollPane plugin is available, which it should be, add our wrapper for it to work and create our nicer scroller for garages with lots of vehicles
		if (jQuery().jScrollPane) {
			tabSelf.find('div.vehicle-cell').wrapAll('<div class="vg-inner-wrap-scrollable" />');
			// Plugin must only run when element is visible so binded to custom global event that Carvenience fires off 
			tabSelf.unbind("Carvenience_Show").bind("Carvenience_Show", function() {
				tabSelf.find("div.vg-inner-wrap-scrollable").jScrollPane({ scrollbarWidth: 12, showArrows: true });
			});
		}
		
		// Hide any alert overlays for vehicle cells
		window.setTimeout(function() {
			tabSelf.find("div.cell-overlay").fadeOut(300);
		}, 2000);
		
		// Compare button to total vehicles and redirect to compare page
		tabSelf.delegate(".compare-vehicles > a", "click", function(event) {
			event.preventDefault();
			var compareLink = this.href,
				totalCompares = 0;
			tabSelf.find("input[name='compare']:checked").each(function() {
				if (totalCompares == 0)
					compareLink = compareLink + 'compare=' + this.value;
				else 
					compareLink = compareLink + '&compare=' + this.value;
				totalCompares++;
			});
			if (totalCompares < 2)
				HNSITE.UI.AlertDialog('Alert Notification', 'Please select at least two vehicles to compare.', {zIndex: 999999});
			else {
				HNSITE.Modules.Carvenience.Close();
				window.location = compareLink;
			}
		});
		
		// Compare button next to each vehicle functionality to add and remove
		tabSelf.find("input[name='compare']").button();
		tabSelf.delegate("input[name='compare']", "click", function(event) {
			var slotHolder = tabSelf.find("ul.compare-box-wrap"), 
				areSlotsFull = ((slotHolder.children("li:not(.checked)").length > 0) ? false : true),
				addSlot = function() {
					var slots = slotHolder.children("li"), 
						stopChecking = false;
					slots.each(function(index) {
						if (!$j(this).is(".checked") && !stopChecking) {
							$j(this).addClass("checked");
							stopChecking = true;
						}
					});
				},
				removeSlot = function() {
					var slotsChecked = slotHolder.children("li.checked");
					if (slotsChecked.length)
						slotsChecked.eq(slotsChecked.length - 1).removeClass("checked");
				};
			
			if ($j(this).is(":checked")) {
				if (!areSlotsFull) addSlot();
				else {
					$j(this).attr('checked', false);
					HNSITE.UI.AlertDialog('Alert Notification', 'You can only compare up to {0} vehicles at a time.'.format(slotHolder.children("li").length), {zIndex: 999999});
				}
			}
			else 
				removeSlot();
		});
		
		// Vehicle title link to details page
		tabSelf.delegate(".vehicle-title > a", "click", function(event) {
			HNSITE.Modules.Carvenience.Close();
			window.location = this.href;
		});
		
		// Vehicle action buttons
		//  -> contact form
		tabSelf.delegate("ul.actions > li.contact-me", "click", function(event) {
			var vehicleName = $j(this).closest(".vehicle-cell").find(".vehicle-title").text(),
				vehicleVin = $j(this).closest(".vehicle-cell").find("input[name='vin']").val(),
				isSold = $j(this).closest(".vehicle-cell").find("input[name='isSold']").val(),
				userData = HNSITE.Modules.User.Account.GetSettings(), 
				defaultComment = (isSold.toLowerCase() == 'true') ? 'Please contact me about similar vehicles for a sold {0}' : 'Please contact me about {0}';
			HNSITE.UI.AjaxForm.Show({
				header: 'Contact Me Now', 
				defaultCover: false, 
				className: 'ajaxform-default', 
				contentFile: '/framework/module-virtualgarage/lead-form.asp', 
				staticPostData: {vin: vehicleVin, isSold: isSold}, 
				prePopulatedFormData: {
					fullname: userData.Name,
					email: userData.Email,
					comments: defaultComment.format(vehicleName)
				}
			});
		});
		//  -> browse similars (for sold vehicles)
		tabSelf.delegate("ul.actions > li.browse-similar", "click", function(event) {
			HNSITE.Modules.Carvenience.Close();
			window.location = $j(this).children("a")[0].href;
		});
		//  -> more information (for in-stock vehicles)
		tabSelf.delegate("ul.actions > li.more-info", "click", function(event) {
			HNSITE.Modules.Carvenience.Close();
			window.location = $j(this).children("a")[0].href;
		});
		//  -> remove vehicle from your garage
		tabSelf.delegate("ul.actions > li.remove-vehicle", "click", function(event) {
			var dialogBox = $j("<div>", {id: "hnsite-ui-dialog-confirm"}).appendTo("body"),
				vehicleCell = $j(this).closest(".vehicle-cell"), 
				cacheID = vehicleCell.find("input[name='cacheID']").val(), 
				destroyBox = function() { dialogBox.dialog("close").dialog("destroy").remove(); };
			
			dialogBox.html('<p>Are you sure you want to remove this vehicle from your Virtual Garage?</p>')
				.dialog({
					modal: true,
					title: "Confirmation Requested",
					closeOnEscape: false,
					zIndex: 999999, 
					resizable: false, 
					buttons: {
						"OK": function() {
							HNSITE.Modules.VirtualGarage.RemoveVehicle(cacheID, {
								onSuccess: function() { 
									vehicleCell.slideUp('fast', function() { 
										// If this vehicle was being compared, uncheck a compare box
										if (vehicleCell.find("> .compare-wrap > label").hasClass("ui-state-active")) {
											var checkedCompareSlots = tabSelf.find("ul.compare-box-wrap > li.checked");
											if (checkedCompareSlots.length)
												checkedCompareSlots.eq(checkedCompareSlots.length - 1).removeClass("checked");
										}
										// Remove the vehicle row permanently and re-zebra stripe to keep it pretty
										vehicleCell.remove(); 
										zebraStripe();
									}); 
									destroyBox(); 
								}, 
								onFail: function() { destroyBox(); }
							});
						},
						"Cancel": function() { destroyBox(); }
					}
				});
		});
	}
	
};

