/**
 * Wrapper around Marin tracking routines
 * 
 * @return
 */
function MarinTracking(conversionType) {
	this.formId = "utmform";
	this.textAreaId = "utmtrans";
	this.conversionType = conversionType;
	this.containerId = "div#contentwrap";
	this.init();
}

MarinTracking.prototype.init = function() {
	this.trackingHandlers = new Object();
	this.trackingHandlers["storeAppointment"] = this.marinImageOverride;
	this.trackingHandlers["emailFriend"] = this.marinImageOverride;
	this.trackingHandlers["printPage"] = this.marinImageOverride;
	this.trackingHandlers["weddingRegistry"] = this.marinImageOverride;
	this.trackingHandlers["addToViewingRoom"] = this.marinImageOverride;
	this.trackingHandlers["addToSavedList"] = this.marinImageOverride;
	this.trackingHandlers["requestCatalog"] = this.marinImageOverride;
	this.trackingHandlers["nonWeddingRegistry"] = this.marinImageOverride;
	this.trackingHandlers["order"] = this.marinImageOverride;
	this.trackingHandlers["accountCreate"] = this.marinImageOverride;

	this.conversionTypes = new Object();
	this.conversionTypes["storeAppointment"] = "appt";
	this.conversionTypes["emailFriend"] = "email";
	this.conversionTypes["printPage"] = "Print";
	this.conversionTypes["weddingRegistry"] = "wed_reg";
	this.conversionTypes["addToViewingRoom"] = "add_item";
	this.conversionTypes["addToSavedList"] = "saved";
	this.conversionTypes["requestCatalog"] = "catalog";
	this.conversionTypes["nonWeddingRegistry"] = "reg";
	
	// order which contains item(s) from a registry
	this.conversionTypes["regorder"] = "reg_sale";
	
	// an order which doesn't contain any item from a registry
	this.conversionTypes["order"] = "sale";
	
	this.conversionTypes["accountCreate"] = "signup";

	// currently not tracked by marin
	this.conversionTypes["phoneOrder"] = "phoneOrder";
	this.conversionTypes["viewingRoom"] = "viewingRoom";
	this.conversionTypes["giftRegistry"] = "reg";
}

// only creates form if it doesn't exist.
// otherwise, if conversion occurs multiple times on the same page
// (e.g., sending email to multiple friends for the same product),
// multiple forms will be created and each friend will be tracked
// one more time than the previous friend.
MarinTracking.prototype.createForm = function() {
	var form = null;
	var contentWrap = jQuery(this.containerId);
	var existingForms = document.getElementsByName(this.formId);

	if (existingForms && existingForms.length > 0) {
		form = existingForms[0];
	} else {
		if (contentWrap.length > 0) {
			form = jQuery(
					"<form style='display:none;' name='utmform' id='"
							+ this.formId + "'></form>").appendTo(contentWrap);
			jQuery("<textarea id='" + this.textAreaId + "'></textarea>")
					.appendTo(form);
		}
	}

	return form;
}

MarinTracking.prototype.createUTMT = function(order) {
	var template = "UTM:T|ORDER_ID|AFFILIATION|TOTAL|TAX|SHIPPING|CITY|STATE|COUNTRY";
	return template
			.replace(/ORDER_ID/, varUtils.hasValue(order.id) ? order.id : "")
			.replace(/AFFILIATION/,
					varUtils.hasValue(order.custId) ? order.custId : "")
			.replace(/TOTAL/, varUtils.hasValue(order.total) ? order.total : "")
			.replace(/TAX/, varUtils.hasValue(order.tax) ? order.tax : "")
			.replace(/SHIPPING/,
					varUtils.hasValue(order.shipping) ? order.shipping : "")
			.replace(/CITY/, varUtils.hasValue(order.city) ? order.city : "")
			.replace(/STATE/, varUtils.hasValue(order.state) ? order.state : "")
			.replace(/COUNTRY/,
					varUtils.hasValue(order.country) ? order.country : "");
}

// if the item has a "conversionType", use it.  otherwise,
// use the "order" - which btw is not always an order.... *sigh*
MarinTracking.prototype.createUTMI = function(order) {
	var template = "UTM:I|ORDER_ID|CONV_TYPE|PRODUCTNAME|CATEGORY|PRICE|QUANTITY";
	var results = "";

	for (var i = 0; i < order.items.length; ++i) {
		results = results
				.concat(template
						.replace(/ORDER_ID/,
								varUtils.hasValue(order.id) ? order.id : "")
						.replace(/CONV_TYPE/,
								varUtils.hasValue(order.items[i].conversionType) ? this.conversionTypes[order.items[i].conversionType]
										: this.conversionTypes[order.conversionType])
						.replace(
								/PRODUCTNAME/,
								varUtils.hasValue(order.items[i].name) ? order.items[i].name
										: "")
						.replace(
								/CATEGORY/,
								varUtils.hasValue(order.items[i].category) ? order.items[i].category
										: "")
						.replace(
								/PRICE/,
								varUtils.hasValue(order.items[i].price) ? order.items[i].price
										: "")
						.replace(
								/QUANTITY/,
								varUtils.hasValue(order.items[i].quantity) ? order.items[i].quantity
										: ""));

		if (i < order.items.length - 1) {
			results = results.concat("\n");
		}
	}

	return results;
}

/**
 * Track an event. Will defer to the declared handler for the event (order type) if one is available
 * otherwise the default utmt and utmi line creation functions are used. 
 */
MarinTracking.prototype.track = function(order) {
	var handler = this.trackingHandlers[order.conversionType];

	if (varUtils.isDef(handler)) {
		handler.call(this, order);
	} else {
		var form = this.createForm();

		if (varUtils.isDef(form)) {
			var text = this.createUTMT(order).concat("\n").concat(
					this.createUTMI(order));
			jQuery("textarea#" + this.textAreaId).text(text);
			_marinTrack.processOrders();
		}
	}
}

/**
 * Overrite Marin's image generating function so that tracking pixels can be generated 
 * as events are triggered and not when then page is rendered.
 */
MarinTracking.prototype.marinImageOverride = function(order) {
	var form = this.createForm();
	var containerId = this.containerId;

	if (varUtils.isDef(form)) {
		var text = this.createUTMT(order).concat("\n").concat(
				this.createUTMI(order));
		jQuery("textarea#" + this.textAreaId).text(text);
		var writeImage = _marinTrack._writeImage;
		_marinTrack["_writeImage"] = function(A) {
			A = A + "&rnd=" + Math.round(Math.random() * 2147483647);
			jQuery('<img src="' + A + '" border="0" height="1" width="1" />')
					.appendTo(containerId);
		}
		_marinTrack.processOrders();
		_marinTrack["_writeImage"] = writeImage;
	}
}

/**
 * A map that translates between Fina's subcodes and human readable text.
 */
function MCFinaSearchUtils() {
	this.data = null;
	this.selectedValues = null;
	this.solrFacetUtils = new SolrFacetUtils();

	this.dropDownCollections = {
		manufacturer : [ "price" ],
		site : [ "designer", "price", "topLevelCategory" ],
		standard : [ "designer", "type", "price" ],
		standardFooter : [ "designer", "type", "price", "pattern" ],

		engagementWeddingDesigner : [ "type", "collection" ],
		engagementWeddingBand : [ "designer", "collection", "style", "price" ],
		engagementWeddingBandFooter : [ "designer", "type", "collection",
				"style", "price" ],

		findYourStyle : [ "designer", "collection", "style", "price" ],

		jewelryFooter : [ "designer", "type", "metal", "stone", "collection",
				"style", "price" ],
		jewelry : [ "designer", "type", "metal", "stone", "collection", "price" ],
		jewelryDesigner : [ "type", "collection" ],

		giftsFooter : [ "designer", "type", "style", "occasion", "recipient",
				"price" ],
		giftsDesigner : [ "type" ],
		gifts : [ "designer", "type", "occasion", "recipient", "price" ],
		giftsByOccasion : [ "designer", "type", "recipient", "price" ],
		giftsByRecipient : [ "designer", "type", "occasion", "price" ],
		giftsByCategory : [ "designer", "occasion", "recipient", "price" ],
		giftsByStyle : [ "designer", "type", "occasion", "recipient", "price" ],
		giftsForBaby : [ "designer", "occasion", "recipient", "price" ],
		giftsFrame : [ "designer", "occasion", "recipient", "price" ],

		homeDecor : [ "designer", "room", "style", "type", "price" ],
		homeDecorByDesigner : [ "room", "style", "type", "price" ],
		homeDecorByRoom : [ "designer", "style", "type", "price" ],
		homeDecorByCategory : [ "designer", "room", "style", "price" ],
		homeDecorByStyle : [ "designer", "room", "type", "price" ],

		tablewareAndEntertainingDesigner : [ "teDesignerCategory" ],
		tablewareAndEntertaining : [ "designer", "price" ],
		vintageSilver : [ "price" ],

		bath : [ "designer", "price" ],
		bathDesigner : [ "price" ], 
		designerSearch : [ "type", "collection" ]		                 
	};

	var submitHandlerData = new Object();
	submitHandlerData["handler"] = this.filterSearchResults;
	submitHandlerData["thisArg"] = this;
	submitHandlerData["args"] = [ jQuery("#searchFilterForm"),
			jQuery("#current_page_id"), 0 ];

	this.submitHandler = new Object();
	this.submitHandler["name"] = "change";
	this.submitHandler["handler"] = this.eventHandlerProxy;
	this.submitHandler["data"] = submitHandlerData;

	var updateHandlerData = new Object();
	updateHandlerData["handler"] = this.updateFilters;
	updateHandlerData["thisArg"] = this;
	updateHandlerData["args"] = [ jQuery("#searchFilterForm") ];

	this.updateHandler = new Object();
	this.updateHandler["name"] = "change";
	this.updateHandler["handler"] = this.eventHandlerProxy;
	this.updateHandler["data"] = updateHandlerData;

	// inserts a blank selection as the first item in the list
	this.perFilterCallback = new Object();
	this.perFilterCallback["post"] = function(container, filter) {
		var item = jQuery("<option></option>").prependTo(
				jQuery("select[name=" + filter.attributes.name + "]"));
		item.attr("value", "");

		var options = {
			filter_by_brand : "All Designers",
			filter_by_category_id : "All Types",
			filter_by_category : "All Types",
			filter_by_collection : "All Collections",
			filter_by_metal : "All Metals",
			filter_by_occasion : "All Occasions",
			filter_by_pattern : "All Patterns",
			filter_by_recipient : "All Recipients",
			filter_by_room : "All Rooms",
			filter_by_stone : "All Gemstones",
			filter_by_style : "All Styles",
			filter_by_type : "All Types",
			filter_by_price : "Price Range"
		};

		item
				.text(varUtils.isDef(options[filter.attributes.name]) ? options[filter.attributes.name]
						: "All");

		if (!varUtils.hasValue(filter.value)) {
			item.attr("selected", true);
		}
	};

	this.perFilterCallbackFooter = new Object();
	this.perFilterCallbackFooter["post"] = this.perFilterCallback["post"];
	this.perFilterCallbackFooter["thisArg"] = this;
	this.perFilterCallbackFooter["render"] = function(container, filter) {
		var labels = {
			filter_by_category : "Category",
			filter_by_collection : "Collection",
			filter_by_brand : "Designer",
			filter_by_stone : "Gemstone",
			filter_by_metal : "Metal",
			filter_by_occasion : "Occasion",
			filter_by_recipient : "Recipient",
			filter_by_room : "Room",
			filter_by_style : "Style",
			filter_by_type : "Type",
			filter_by_price : "Price"
		};

		var listItem = jQuery("<li></li>").appendTo(container);
		var label = jQuery("<label></label>").appendTo(listItem);
		label.attr("for", filter.attributes.name);
		label.attr("class", "label");
		label
				.text(varUtils.isDef(labels[filter.attributes.name]) ? labels[filter.attributes.name]
						: "No Label");

		this.solrFacetUtils.filterCallbacks.render.call(this.solrFacetUtils,
				listItem, filter);
	}

	this.perTopLevelCatCallback = new Object();
	this.perTopLevelCatCallback["thisArg"] = this.perTopLevelCatCallback;
	this.perTopLevelCatCallback["solrFacetUtils"] = this.solrFacetUtils;
	this.perTopLevelCatCallback["render"] = function(container, filter,
			filterItem, index) {
		var topLevelCats = [ "engagement & wedding bands", "jewelry", "gifts",
				"tableware & entertaining", "home decor", "bath" ];
		if (topLevelCats.indexOf(filterItem.term.toLowerCase()) >= 0) {
			this.solrFacetUtils.filterCallbacks.itemRender(container, filter,
					filterItem, index);
		}
	};

	this.perTECatCallback = new Object();
	this.perTECatCallback["thisArg"] = this.perTopLevelCatCallback;
	this.perTECatCallback["solrFacetUtils"] = this.solrFacetUtils;
	this.perTECatCallback["render"] = function(container, filter, filterItem,
			index) {
		var topLevelCats = [ "bar accessories", "casual dinnerware",
				"flatware", "formal china", "stem and barware" ];
		if (topLevelCats.indexOf(filterItem.term.toLowerCase()) >= 0) {
			this.solrFacetUtils.filterCallbacks.itemRender(container, filter,
					filterItem, index);
		}
	};

	this.priceCallback = new Object();
	this.priceCallback["thisArg"] = this;
	this.priceCallback["render"] = function(container, filter, filterItem,
			index) {
		if (filter.attributes.name == "filter_by_price") {
			var item = new Object();
			item["term"] = filterItem.term;
			item["label"] = this.solrFacetUtils.formatters
					.formatPrice(filterItem.label);
			filterItem = item;
		}
		this.solrFacetUtils.filterCallbacks.itemRender(container, filter,
				filterItem, index);
	};
}

MCFinaSearchUtils.prototype.setSolrFacetUtils = function(solrFacetUtils) {
	this.solrFacetUtils = solrFacetUtils;
}

/**
 * Sets up internal data structures.
 */
MCFinaSearchUtils.prototype.init = function(searchResponse, selectedValues) {
	this.selectedValues = selectedValues;

	var json = searchResponse;
	if (varUtils.isDef(searchResponse)) {
		json = varUtils.stringToJSON(json);

		if (!varUtils.isDef(json["searchFailed"]) || !json["searchFailed"]) {
			this.data = this.solrFacetUtils.convertFacetsToObjects(json, 1);
		}
	}
}

MCFinaSearchUtils.prototype.uriDecode = function(value) {
	var decoded = value;
	if (varUtils.hasValue(value)) {
		decoded = decodeURIComponent(value);
	}

	return decoded;

}
/**
 * Drop down factory. Builds a set of drop downs for <code>collection</code>. You'll need to initialize
 * this class with the Solr data before calling this function as that is what the drop downs are populated with.
 */
MCFinaSearchUtils.prototype.buildFilters = function(collection, eventHandler) {
	var filters = null;
	if (varUtils.isDef(this.data) && varUtils.isDef(this.data.facetFields)) {
		var facetFields = this.data.facetFields;
		if (varUtils.isDef(collection)) {
			var collections = this.dropDownCollections[collection];
			filters = new Array();
			var domUtils = new DomUtils();
			for ( var i = 0; i < collections.length; ++i) {
				if (collections[i] == "designer") {
					filters.push(domUtils.buildDomObject( {
						name : "filter_by_brand",
						"class" : "select"
					}, [ eventHandler ], facetFields.facet_brand, this
							.uriDecode(this.selectedValues.filter_by_brand)));
				} else if (collections[i] == "category") {
					filters
							.push(domUtils
									.buildDomObject(
											{
												name : "filter_by_category",
												"class" : "select"
											},
											[ eventHandler ],
											facetFields.facet_category,
											this
													.uriDecode(this.selectedValues.filter_by_category)));
				} else if (collections[i] == "collection") {
					filters
							.push(domUtils
									.buildDomObject(
											{
												name : "filter_by_collection",
												"class" : "select"
											},
											[ eventHandler ],
											facetFields.facet_collection,
											this
													.uriDecode(this.selectedValues.filter_by_collection)));
				} else if (collections[i] == "metal") {
					filters.push(domUtils.buildDomObject( {
						name : "filter_by_metal",
						"class" : "select"
					}, [ eventHandler ], facetFields.facet_metal, this
							.uriDecode(this.selectedValues.filter_by_metal)));
				} else if (collections[i] == "occasion") {
					filters
							.push(domUtils
									.buildDomObject(
											{
												name : "filter_by_occasion",
												"class" : "select"
											},
											[ eventHandler ],
											facetFields.facet_occasion,
											this
													.uriDecode(this.selectedValues.filter_by_occasion)));
				} else if (collections[i] == "pattern") {
					filters.push(domUtils.buildDomObject( {
						name : "filter_by_pattern",
						"class" : "select"
					}, [ eventHandler ], facetFields.facet_pattern, this
							.uriDecode(this.selectedValues.filter_by_pattern)));
				} else if (collections[i] == "price") {
					filters.push(domUtils.buildDomObject( {
						name : "filter_by_price",
						"class" : "select"
					}, [ eventHandler ], facetFields.price, this
							.uriDecode(this.selectedValues.filter_by_price),
							this.priceCallback));
				} else if (collections[i] == "recipient") {
					filters
							.push(domUtils
									.buildDomObject(
											{
												name : "filter_by_recipient",
												"class" : "select"
											},
											[ eventHandler ],
											facetFields.facet_recipient,
											this
													.uriDecode(this.selectedValues.filter_by_recipient)));
				} else if (collections[i] == "room") {
					filters.push(domUtils.buildDomObject( {
						name : "filter_by_room",
						"class" : "select"
					}, [ eventHandler ], facetFields.facet_room, this
							.uriDecode(this.selectedValues.filter_by_room)));
				} else if (collections[i] == "stone") {
					filters.push(domUtils.buildDomObject( {
						name : "filter_by_stone",
						"class" : "select"
					}, [ eventHandler ], facetFields.facet_stone, this
							.uriDecode(this.selectedValues.filter_by_stone)));
				} else if (collections[i] == "style") {
					filters.push(domUtils.buildDomObject( {
						name : "filter_by_style",
						"class" : "select"
					}, [ eventHandler ], facetFields.facet_style, this
							.uriDecode(this.selectedValues.filter_by_style)));
				} else if (collections[i] == "type") {
					filters.push(domUtils.buildDomObject( {
						name : "filter_by_type",
						"class" : "select"
					}, [ eventHandler ], facetFields.facet_type, this
							.uriDecode(this.selectedValues.filter_by_type)));
				} else if (collections[i] == "topLevelCategory") {
					//Build data
					filters.push(domUtils.buildDomObject( {
						name : "filter_by_category",
						"class" : "select"
					}, [ eventHandler ], facetFields.facet_category, this
							.uriDecode(this.selectedValues.filter_by_category),
							this.perTopLevelCatCallback));
				} else if (collections[i] == "teDesignerCategory") {
					//Build data
					filters.push(domUtils.buildDomObject( {
						name : "filter_by_category",
						"class" : "select"
					}, [ eventHandler ], facetFields.facet_category, this
							.uriDecode(this.selectedValues.filter_by_category),
							this.perTECatCallback));
				}
			}
		}
	}

	return filters;
}

/**
 * Builds and renders the drop downs. Will initialize with the passed in data object/string if it hasn't been done yet.
 */
MCFinaSearchUtils.prototype.installFilters = function(dropDowns, data,
		selectedValues) {
	try {
		if (varUtils.isDef(data) && varUtils.isDef(selectedValues)) {
			this.init(data, selectedValues);
		}
		if (varUtils.isDef(window["searchType"])) {
			var eventHandler = this.submitHandler;
			var filterCallback = this.perFilterCallback;

			var vertFilters = jQuery("ol#searchFilterFormControls");
			var horzFilters = jQuery("fieldset#searchFilterFormControls");
			if (vertFilters.length > 0) {
				eventHandler = this.updateHandler;
				filterCallback = this.perFilterCallbackFooter;
				if (dropDowns == "engagementWeddingBand") {
					dropDowns = dropDowns.concat("Footer");
				}
			} else if (searchType == "cat_gifts_search") {
				//Extra help for the gifts category
				var pageTitle = jQuery("h2.pagetitle");
				if (pageTitle.length > 0) {
					var title = pageTitle[0].innerHTML.toLowerCase();
					if (title == "for baby") {
						dropDowns = "giftsForBaby";
					} else if (title == "frames") {
						dropDowns = "giftsFrame";
					}
				}
			}

			var filters = this.buildFilters(dropDowns, eventHandler);
			this.solrFacetUtils.renderFilters(
					jQuery("#searchFilterFormControls"), filters,
					filterCallback);
			this.installMissingFilters(dropDowns);
		}
	} catch (e) {
		//silence
		alert(e);
	}
}

/**
 * When initiating a search from a top level category landing page that renders the results on a 
 * lower tier category landing page, not all of the filters available on the top level page will be
 * present on the lower tier page. If the customer has select values from one of these 'missing' filters
 * this routine renders them as hidden so their impact on the over search results remains. 
 */
MCFinaSearchUtils.prototype.installMissingFilters = function(dropDowns) {
	var startIndex = "filter_by_".length;
	var collections = this.dropDownCollections[dropDowns]
	for ( var filter in this.selectedValues) {
		if (varUtils.hasValue(this.selectedValues[filter])
				&& filter.indexOf("filter_by_") == 0) {
			var filterName = filter.substr(startIndex);
			var index = collections.indexOf(filterName);
			if (!(index >= 0)) {
				var input = jQuery("<input type='hidden'/>").appendTo(
						jQuery("#searchFilterForm"));
				input.attr("name", filter);
				input.attr("value", this.selectedValues[filter]);
			}
		}
	}
}

/**
 * Initalizes and installs search related functionality on the page:
 * <ul><li>Autocomplete</li><li>Filters</li><li>Term suggestion (for misspellings)</li></ul>
 */
MCFinaSearchUtils.prototype.initSearch = function(dropDowns, data,
		selectedValues) {
	this.init(data, selectedValues);
	var autocompleteURL = "http://ext-sieve.acacloud.com/solr/mcfina_products/spell?json.wrf=?";
	this.installAutocomplete(autocompleteURL);

	var searchSuggestions = jQuery("div#search_suggestions");
	if (searchSuggestions.length > 0) {
		(new SolrTermSuggest()).renderTermSuggestions(
				jQuery("#search_suggestions"),
				(contextPath + "/sitesearch/search_do"), varUtils
						.stringToJSON(data));
	} else {
		//On search results page.
		if (window.location.pathname.indexOf("search_do") >= 0) {
			this.installFilters(dropDowns);
		} else {
			var liveQuery = true;
			var filterForm = jQuery("form#searchFilterForm");
			if (filterForm.length > 0) {
				if (liveQuery) {
					this.installLiveFilters();
				} else {
					this.init(data, selectedValues);
					this.installFilters(dropDowns);
				}
			}
		}
	}
}

/**
 * Adapts JQuery event handling mechanism to our classes, that is, the this argument
 * and parameters are pulled from the event object itself (you'll obviously need to set this up
 * when you create your events).
 */
MCFinaSearchUtils.prototype.eventHandlerProxy = function(event) {
	event.data.handler.apply(event.data.thisArg, event.data.args);
}

/**
 * Event handler for filter change actions. Just submits the parent form.
 */
MCFinaSearchUtils.prototype.filterSearchResults = function(form, pageField,
		page) {
	if (varUtils.isDef(pageField)) {
		pageField.val(page);
	}
	form.submit();
}

/**
 * Handles the change events from filters so that the remaining filters contain mutually
 * applicable values.
 */
MCFinaSearchUtils.prototype.updateFilters = function(form) {
	var params = new Object();
	params["search_type"] = "filter_refresh";
	params["resultSetSize"] = 0;
	params["primary_search_type"] = form[0].search_type.value;
	var selectedValues = new Object();
	var selectBoxes = jQuery("select[name^='filter_by']");
	for ( var i = 0; i < selectBoxes.length; ++i) {
		var value = selectBoxes[i].value;
		if (varUtils.hasValue(value)) {
			var decoded = decodeURIComponent(value);
			params[selectBoxes[i].name] = decoded;
			selectedValues[selectBoxes[i].name] = decoded;
		}
	}
	var solrWrapper = this;
	jQuery.getJSON(form[0].action, params, function(responseData) {
		jQuery("ol#searchFilterFormControls").empty();
		solrWrapper.installFilters(dropDownSet, responseData, selectedValues);
	});
}

/**
 * Sets up the autocomplete plug in on the global search box. 
 */
MCFinaSearchUtils.prototype.installAutocomplete = function(proxy) {
	var autocomplete = new SolrAutocomplete();
	autocomplete.installAutocomplete(proxy, jQuery("#search"),
			[ "facet_brand" ], [ "brand", "name", "sku", "image_url",
					"is_pattern", "dynamic_url", "static_url" ]);
}
/**
 * Builder for live search query. Returns results to populate the filters.
 */
MCFinaSearchUtils.prototype.installLiveFilters = function() {
	var url = "http://ext-sieve.acacloud.com/solr/mcfina_products/spell?json.wrf=?";
	var solrQueryUtils = new SolrQueryUtils(url, "json");

	solrQueryUtils.addFacetParam("f.facet_brand.facet.limit", -1);
	solrQueryUtils.addFacetParam("f.facet_collection.facet.limit", -1);
	solrQueryUtils.addFacetParam("f.facet_pattern.facet.limit", -1);

	solrQueryUtils.addFacetField("sort_name");
	solrQueryUtils.addFacetField("facet_brand");
	solrQueryUtils.addFacetField("facet_category");
	solrQueryUtils.addFacetField("category_id");
	solrQueryUtils.addFacetField("facet_metal");
	solrQueryUtils.addFacetField("facet_pattern");
	solrQueryUtils.addFacetField("facet_collection");
	solrQueryUtils.addFacetField("facet_stone");
	solrQueryUtils.addFacetField("facet_type");
	solrQueryUtils.addFacetField("facet_style");
	solrQueryUtils.addFacetField("facet_room");
	solrQueryUtils.addFacetField("facet_recipient");
	solrQueryUtils.addFacetField("facet_occasion");
	solrQueryUtils.addFacetField("product_attributes");

	var searchType = jQuery("form#searchFilterForm input[name='search_type']")
			.val();
	if (searchType == "cat_gifts_search") {
		solrQueryUtils.addFacetQuery(solrQueryUtils.makeRangeParameter(false,
				true, false, true, "price", [ 0, 5000 ]));
		solrQueryUtils.addFacetQuery(solrQueryUtils.makeRangeParameter(false,
				true, false, true, "price", [ 5000, 10000 ]));
		solrQueryUtils.addFacetQuery(solrQueryUtils.makeRangeParameter(false,
				true, false, true, "price", [ 10000, 15000 ]));
		solrQueryUtils.addFacetQuery(solrQueryUtils.makeRangeParameter(false,
				true, false, true, "price", [ 15000, 20000 ]));
		solrQueryUtils.addFacetQuery(solrQueryUtils.makeRangeParameter(false,
				true, false, true, "price", [ 20000, 25000 ]));
	} else {
		solrQueryUtils.addFacetQuery(solrQueryUtils.makeRangeParameter(false,
				true, false, true, "price", [ 0, 25000 ]));
	}

	solrQueryUtils.addFacetQuery(solrQueryUtils.makeRangeParameter(false, true,
			false, true, "price", [ 25000, 50000 ]));
	solrQueryUtils.addFacetQuery(solrQueryUtils.makeRangeParameter(false, true,
			false, true, "price", [ 50000, 75000 ]));
	solrQueryUtils.addFacetQuery(solrQueryUtils.makeRangeParameter(false, true,
			false, true, "price", [ 75000, 100000 ]));
	solrQueryUtils.addFacetQuery(solrQueryUtils.makeRangeParameter(false, true,
			false, true, "price", [ 100000, 150000 ]));
	solrQueryUtils.addFacetQuery(solrQueryUtils.makeRangeParameter(false, true,
			false, true, "price", [ 150000, 200000 ]));
	solrQueryUtils.addFacetQuery(solrQueryUtils.makeRangeParameter(false, true,
			false, true, "price", [ 200000, 250000 ]));
	solrQueryUtils.addFacetQuery(solrQueryUtils.makeRangeParameter(false, true,
			false, true, "price", [ 250000, 300000 ]));
	solrQueryUtils.addFacetQuery(solrQueryUtils.makeRangeParameter(false, true,
			false, true, "price", [ 300000, 400000 ]));
	solrQueryUtils.addFacetQuery(solrQueryUtils.makeRangeParameter(false, true,
			false, true, "price", [ 400000, 500000 ]));
	solrQueryUtils.addFacetQuery(solrQueryUtils.makeRangeParameter(false, true,
			false, true, "price", [ 500000, Infinity ]));

	var finaSearchUtils = this;
	var jsonCallback = function(data, status) {
		finaSearchUtils.installFilters(dropDownSet, data, selectedValues);
	}

	var updateCategoryIdList = function(data, status) {
		solrQueryUtils.addQueryParameter(solrQueryUtils
				.makeMultiValueParameter(true, false, "category_id", data));
	}

	try {
		var params = new Object();
		if (searchType == "manufacturer_cat_search") {
			var brand = jQuery("form#searchFilterForm input[name='man_name']")
					.val();
			solrQueryUtils
					.addQueryParameter(solrQueryUtils.makeSingleValueParameter(
							true, false, "facet_brand", brand));

			if (dropDownSet == "tablewareAndEntertainingDesigner") {

				// image is not required for a designer/tableware category search.
			} else {
				solrQueryUtils.addQueryParameter(solrQueryUtils
						.makeSingleValueParameter(false, false, "has_image",
								"false"));
			}
		}

		if (!(dropDownSet == "tablewareAndEntertainingDesigner" || dropDownSet == "tablewareAndEntertaining")) {
			solrQueryUtils.addQueryParameter(solrQueryUtils
					.makeSingleValueParameter(false, false, "is_pattern",
							"true"));
			solrQueryUtils.addQueryParameter(solrQueryUtils.makeRangeParameter(
					false, false, false, true, "price", [ -Infinity, 0 ]));
		}

		var catid = jQuery("form#searchFilterForm input[name='cat_id']").val();
		params["catId"] = catid;
		jQuery.get(contextPath
				+ "/views/common/search/solrProxyCatalogHelper.jsp", params,
				function(data, status) {
					updateCategoryIdList(data, status);
					solrQueryUtils.forwardToProxy(0, 0, null, jsonCallback,
							false);
				}, "json");
	} catch (e) {
		alert(e);
	}
}

/**
 * Yahoo User Interface version of autocomplete. Works but conflicts with Fina's styling.
 */
/*
 * MCFinaSearchUtils.prototype.installAutocompleteYUI=function(proxy,
 * targetElementId, targetContainerId){ var dsXHR = new
 * YAHOO.util.XHRDataSource(proxy);
 * dsXHR.responseType=YAHOO.util.XHRDataSource.TYPE_JSON; dsXHR.responseSchema = {
 * fields : [ { key: "name" } ] };
 * 
 * dsXHR.parseJSONData=function(request , response){ var data=new Object();
 * data["results"]=new Array();
 * 
 * var iterator=function(title,yuiSchemaKey,items){ var values=new Array(); for
 * (var i=0; i<items.length;i+=2){ var item=new Object();
 * item[yuiSchemaKey]=items[i]; values.push(item); } return values; }
 * 
 * try {
 * data["results"]=data["results"].concat(iterator("Brand","name",response.facet_counts.facet_fields.facet_brand)); }
 * catch (e){ //alert(e); data=false; }
 * 
 * return data; }
 * 
 * var solrQueryUtils=new SolrQueryUtils(proxy,"json");
 * solrQueryUtils.addFacetField("facet_brand");
 * 
 * var aComplete=new
 * YAHOO.widget.AutoComplete(targetElementId,targetContainerId, dsXHR);
 * aComplete.generateRequest=function(sQuery){ solrQueryUtils.resetQuery();
 * solrQueryUtils.addQueryParameter(solrQueryUtils.makeSingleValueParameter(false,true,"brand",sQuery+"*"));
 * var query=solrQueryUtils.getQueryString(0,0,false,true); return "?"+query; } }
 */

function MCFinaPaginationUtils(solrResultPaginator, data) {
	this.solrResultPaginator = solrResultPaginator;
	this.data = null;
	if (varUtils.hasValue(data)) {
		this.data = varUtils.stringToJSON(data);
	}
}

MCFinaPaginationUtils.prototype.setResultPaginator = function(resultPaginator) {
	this.solrResultPaginator = resultPaginator;
}

/**
 * Renders the pagination controls and search results.
 */
MCFinaPaginationUtils.prototype.renderPage = function(container, imageSize,
		linkType, insert_zoomed_image) {
	try {
		var callbacks = new Object();

		callbacks["render"] = function(container, documents, document, index) {
			var listItem = jQuery('<li></li>').appendTo(container);
			if (insert_zoomed_image) {
				listItem.attr("id", "prod_image_li_" + document.id);
				listItem.attr("style", "z-index: 10; min-height: 210px;");
			}

			var anchor = jQuery("<a></a>").appendTo(listItem);
			var link = document[linkType].replace(/^null/, contextPath);
			anchor.attr("href", "/" + link);
			anchor.attr("title", document.name + " by " + document.brand);

			if (!insert_zoomed_image) {

				// when not inserting the zoomed-in image, we still need to show the regular image.
				var imageUtils = new ImageUtils(contextPath, staticImgPath,
						fluidBaseItemURL);
				var imageTag = imageUtils
						.getProductImgTag(
								document.sku,
								imageSize,
								document.name,
								false,
								(!varUtils.isDef(document.image_url) || (document.pattern && document.image_url == "images/placeholder100x100.jpg")),
								false);
				jQuery(imageTag).appendTo(anchor);
			}

			jQuery("<br/>").appendTo(anchor);
			var patternName = undefined;
			if (varUtils.isDef(document.pattern_name)
					&& document.pattern_name.length > 0) {
				if (typeof document.pattern_name == "string") {
					patternName = document.pattern_name;
				} else {
					patternName = document.pattern_name[0];
				}
			}

			(jQuery("<span></span>").appendTo(anchor)).text(varUtils
					.isDef(patternName) ? patternName : document.name);
			jQuery("<br/>").appendTo(anchor);
			(jQuery("<span></span>").appendTo(anchor)).text("by "
					+ document.brand);

			if (!document.is_pattern && varUtils.isDef(patternName)) {
				jQuery("<br/>").appendTo(anchor);
				(jQuery("<span></span>").appendTo(anchor)).text(document.name);

				// The multiplier depends on how the price is stored in the db -
				// check to ensure this is correct.
				var unformatted = parseInt(document.price * 1);
				var price = varUtils
						.formatCurrency(convert_to_dollars(unformatted));
				if(document.brand != 'Heather Moore') {
					jQuery("<br/>").appendTo(listItem);
					(jQuery("<span></span>").appendTo(listItem))
							.text(((unformatted + 0) > 0 ? "$" + price : ""));
				}
			}
		}

		var domUtils = new DomUtils();
		this.solrResultPaginator.renderPagination((jQuery("<p></p>")
				.appendTo(container)).attr("id", "upperPaginationContainer")
				.attr("class", "paging"), this.data.response.numFound);
		(new SolrDocumentUtils()).renderDocuments((jQuery("<div></div>")
				.appendTo(container)).attr("class", "products"), domUtils
				.buildDomObject(null, null, this.data.response.docs, null,
						callbacks));
		this.solrResultPaginator.renderPagination((jQuery("<p></p>")
				.appendTo(container)).attr("id", "lowerPaginationContainer")
				.attr("class", "paging"), this.data.response.numFound);

		if (insert_zoomed_image) {

			// padding so that the bottom of the zoomed-in image doesn't get hidden by the footer.
			(jQuery('<div><br></div>').appendTo(container)).attr('style',
					'clear: both');

			var static_linking = '';
			if (linkType == 'static_url') {
				static_linking = 't';
			}

			for ( var i = 0; i < this.data.response.docs.length; i++) {
				insert_image('medium',
						'prod_image_li_' + this.data.response.docs[i].id,
						this.data.response.docs[i], static_linking, 'before',
						false, true, false);
			}
		}
	} catch (e) {
		//alert(e);
	}
}

function MCFinaPageUtils() {
}

/**
 * Check if the browser has flash enabled and insert a static image if not.
 */
MCFinaPageUtils.prototype.checkFlash = function() {
	var productFlashContainer = "div#display:905:SKU:detail.fluid-display";

	if (!pageInfo.envInfo.isFlashEnabled) {
		if (varUtils.isDef(pageInfo.product)
				&& varUtils.hasValue(pageInfo.product.sku)) {
			var fluidContainer = jQuery(productFlashContainer.replace(/SKU/,
					pageInfo.product.sku));
			if (fluidContainer.length > 0) {
				var imageTag = (new ImageUtils(pageInfo.pathInfo.contextPath,
						pageInfo.pathInfo.staticImgPath,
						pageInfo.pathInfo.fluidBaseItemURL)).imageUtils
						.getProductImgTag(pageInfo.product.sku, "detail",
								pageInfo.product.name, true, false, false);
				jQuery(imageTag).appendTo(fluidContainer);
			}
		}
	}
}

/**
 * Check if this page is to be printed.
 * 
 * @param checkFlash - Set to <code>true</code> if you also want to check if shockwave/flash is enabled.
 */
MCFinaPageUtils.prototype.printCheck = function(checkFlash) {
	var isPrint = urlUtils.getQueryStringParam("print");
	if (varUtils.isTrue(isPrint) && varUtils.isDef(product)) {
		var imageUtils = new ImageUtils(contextPath, staticBaseItemURL,
				fluidBaseItemURL);
		jQuery("div.static-display").append(
				imageUtils.getProductImgTag(product.sku, "detail",
						product.name, true, false));
	}
	if (varUtils.isTrue(checkFlash)) {
		this.checkFlash();
	}
}

